wasm/c: add support for class flags

This commit is contained in:
Alexey Andreev 2023-11-08 21:02:31 +01:00
parent 7ef7926519
commit 083ecbdad2
8 changed files with 73 additions and 15 deletions

View File

@ -740,12 +740,24 @@ public class ClassGenerator {
sizeExpr = "0";
}
if (cls != null) {
if (cls.hasModifier(ElementModifier.ENUM)) {
flags |= RuntimeClass.ENUM;
if (cls.hasModifier(ElementModifier.ABSTRACT)) {
flags |= RuntimeClass.ABSTRACT;
}
if (cls.hasModifier(ElementModifier.INTERFACE)) {
flags |= RuntimeClass.INTERFACE;
}
if (cls.hasModifier(ElementModifier.FINAL)) {
flags |= RuntimeClass.FINAL;
}
if (cls.hasModifier(ElementModifier.ANNOTATION)) {
flags |= RuntimeClass.ANNOTATION;
}
if (cls.hasModifier(ElementModifier.SYNTHETIC)) {
flags |= RuntimeClass.SYNTHETIC;
}
if (cls.hasModifier(ElementModifier.ENUM)) {
flags |= RuntimeClass.ENUM;
}
}
List<TagRegistry.Range> ranges = tagRegistry != null ? tagRegistry.getRanges(className) : null;
tag = !context.isIncremental() && ranges != null && !ranges.isEmpty() ? ranges.get(0).lower : 0;

View File

@ -45,6 +45,7 @@ public class PlatformClassIntrinsic implements Intrinsic {
break;
case "setJavaClass":
break;
case "getFlags":
}
}
}

View File

@ -34,6 +34,8 @@ public class PlatformClassMetadataIntrinsic implements Intrinsic {
RuntimeClass.class.getName(), "declaringClass");
private static final FieldReference ENCLOSING_CLASS_FIELD = new FieldReference(
RuntimeClass.class.getName(), "enclosingClass");
private static final FieldReference FLAGS_FIELD = new FieldReference(
RuntimeClass.class.getName(), "flags");
@Override
public boolean canHandle(MethodReference method) {
@ -47,6 +49,7 @@ public class PlatformClassMetadataIntrinsic implements Intrinsic {
case "getSimpleName":
case "getDeclaringClass":
case "getEnclosingClass":
case "getFlags":
return true;
}
return false;
@ -81,6 +84,11 @@ public class PlatformClassMetadataIntrinsic implements Intrinsic {
case "getEnclosingClass":
printFieldAccess(context, invocation, ENCLOSING_CLASS_FIELD);
break;
case "getFlags":
context.writer().print("(");
printFieldAccess(context, invocation, FLAGS_FIELD);
context.writer().print(" >> " + RuntimeClass.FLAGS_SHIFT + ")");
break;
}
}

View File

@ -18,6 +18,10 @@ package org.teavm.backend.wasm.intrinsics;
import org.teavm.ast.InvocationExpr;
import org.teavm.ast.QualificationExpr;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
import org.teavm.backend.wasm.model.expression.WasmIntType;
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReference;
@ -32,6 +36,7 @@ public class PlatformClassMetadataIntrinsic implements WasmIntrinsic {
private static final FieldReference SIMPLE_NAME_FIELD = new FieldReference(RUNTIME_CLASS, "simpleName");
private static final FieldReference ENCLOSING_CLASS_FIELD = new FieldReference(RUNTIME_CLASS, "enclosingClass");
private static final FieldReference DECLARING_CLASS_FIELD = new FieldReference(RUNTIME_CLASS, "declaringClass");
private static final FieldReference FLAGS_FIELD = new FieldReference(RUNTIME_CLASS, "flags");
@Override
public boolean isApplicable(MethodReference methodReference) {
@ -45,6 +50,7 @@ public class PlatformClassMetadataIntrinsic implements WasmIntrinsic {
case "getSimpleName":
case "getEnclosingClass":
case "getDeclaringClass":
case "getFlags":
return true;
}
return false;
@ -65,6 +71,11 @@ public class PlatformClassMetadataIntrinsic implements WasmIntrinsic {
return fieldAccess(manager, invocation, ENCLOSING_CLASS_FIELD);
case "getDeclaringClass":
return fieldAccess(manager, invocation, DECLARING_CLASS_FIELD);
case "getFlags": {
var flags = fieldAccess(manager, invocation, FLAGS_FIELD);
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHR_UNSIGNED, flags,
new WasmInt32Constant(RuntimeClass.FLAGS_SHIFT));
}
default:
return new WasmUnreachable();
}

View File

@ -21,14 +21,29 @@ import org.teavm.interop.Unmanaged;
public class RuntimeClass extends RuntimeObject {
public static final int INITIALIZED = 1;
public static final int PRIMITIVE = 2;
public static final int ENUM = 4;
public static final int SYNTHETIC = 1024;
public static final int PRIMITIVE_SHIFT = 3;
public static final int PRIMITIVE_SHIFT = 2;
public static final int PRIMITIVE_MASK = 15;
public static final int VM_TYPE_SHIFT = 7;
public static final int VM_TYPE_SHIFT = 6;
public static final int VM_TYPE_MASK = 7;
public static final int FLAGS_SHIFT = 9;
public static final int ABSTRACT = 1 << FLAGS_SHIFT;
public static final int INTERFACE = 1 << (FLAGS_SHIFT + 1);
public static final int FINAL = 1 << (FLAGS_SHIFT + 2);
public static final int ENUM = 1 << (FLAGS_SHIFT + 3);
public static final int ANNOTATION = 1 << (FLAGS_SHIFT + 4);
public static final int SYNTHETIC = 1 << (FLAGS_SHIFT + 5);
public static final int BRIDGE = 1 << (FLAGS_SHIFT + 6);
public static final int DEPRECATED = 1 << (FLAGS_SHIFT + 7);
public static final int NATIVE = 1 << (FLAGS_SHIFT + 8);
public static final int STATIC = 1 << (FLAGS_SHIFT + 9);
public static final int STRICT = 1 << (FLAGS_SHIFT + 10);
public static final int SYNCHRONIZED = 1 << (FLAGS_SHIFT + 11);
public static final int TRANSIENT = 1 << (FLAGS_SHIFT + 12);
public static final int VARARGS = 1 << (FLAGS_SHIFT + 13);
public static final int VOLATILE = 1 << (FLAGS_SHIFT + 14);
public static final int BOOLEAN_PRIMITIVE = 0;
public static final int BYTE_PRIMITIVE = 1;
public static final int SHORT_PRIMITIVE = 2;

View File

@ -32,7 +32,6 @@ import org.teavm.junit.TeaVMTestRunner;
import org.teavm.junit.TestPlatform;
@RunWith(TeaVMTestRunner.class)
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY, TestPlatform.WASI})
public class ClassTest {
@Test
public void classNameEvaluated() {
@ -115,6 +114,7 @@ public class ClassTest {
}
@Test
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY, TestPlatform.WASI})
public void instanceCreatedThroughReflection() throws Exception {
Runnable instance = (Runnable) Class.forName(TestObject.class.getName()).newInstance();
instance.run();
@ -123,6 +123,7 @@ public class ClassTest {
}
@Test
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY, TestPlatform.WASI})
public void instanceCreatedThoughReflectionWithConstantName() throws Exception {
var cls = Class.forName("org.teavm.classlib.java.lang.ClassTest$ClassReferredByConstantName");
assertArrayEquals(new Class<?>[] { Supplier.class }, cls.getInterfaces());
@ -137,6 +138,7 @@ public class ClassTest {
}
@Test
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY, TestPlatform.WASI})
public void instanceCreatedThroughReflectionAsync() throws Exception {
Runnable instance = TestObjectAsync.class.newInstance();
instance.run();
@ -178,6 +180,7 @@ public class ClassTest {
}
@Test
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY})
public void annotationsExposed() {
Annotation[] annotations = A.class.getAnnotations();
assertEquals(1, annotations.length);
@ -185,6 +188,7 @@ public class ClassTest {
}
@Test
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY})
public void annotationFieldsExposed() {
AnnotWithDefaultField annot = B.class.getAnnotation(AnnotWithDefaultField.class);
assertEquals(2, annot.x());
@ -193,6 +197,7 @@ public class ClassTest {
}
@Test
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY})
public void annotationFieldTypesSupported() {
AnnotWithVariousFields annot = D.class.getAnnotation(AnnotWithVariousFields.class);
assertEquals(true, annot.a());
@ -213,6 +218,7 @@ public class ClassTest {
}
@Test
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY})
public void getInterfaces() {
assertEquals(0, SuperclassWithoutInterfaces.class.getInterfaces().length);
assertEquals(Set.of(TestInterface1.class, TestInterface2.class),

View File

@ -36,9 +36,7 @@ import java.util.Objects;
import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.teavm.junit.SkipPlatform;
import org.teavm.junit.TeaVMTestRunner;
import org.teavm.junit.TestPlatform;
@RunWith(TeaVMTestRunner.class)
public class EnumMapTest {
@ -295,7 +293,6 @@ public class EnumMapTest {
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
@SkipPlatform({TestPlatform.WEBASSEMBLY, TestPlatform.WASI})
public void putAll() {
EnumMap enumColorMap = new EnumMap(Color.class);
enumColorMap.put(Color.Green, 2);

View File

@ -15,13 +15,22 @@
*/
package org.teavm.classlib.java.util;
import static org.junit.Assert.*;
import java.util.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.teavm.junit.SkipPlatform;
import org.teavm.junit.TeaVMTestRunner;
import org.teavm.junit.TestPlatform;
@RunWith(TeaVMTestRunner.class)
public class EnumSetTest {
@ -199,7 +208,6 @@ public class EnumSetTest {
}
@Test
@SkipPlatform({ TestPlatform.WEBASSEMBLY, TestPlatform.WASI })
public void iterator() {
Set<EnumFoo> set = EnumSet.noneOf(EnumFoo.class);
set.add(EnumFoo.a);