diff --git a/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java b/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java index 6b7d0ec9e..397c35d54 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java +++ b/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java @@ -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 ranges = tagRegistry != null ? tagRegistry.getRanges(className) : null; tag = !context.isIncremental() && ranges != null && !ranges.isEmpty() ? ranges.get(0).lower : 0; diff --git a/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassIntrinsic.java b/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassIntrinsic.java index 26bd02bd6..75440d1a9 100644 --- a/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassIntrinsic.java @@ -45,6 +45,7 @@ public class PlatformClassIntrinsic implements Intrinsic { break; case "setJavaClass": break; + case "getFlags": } } } diff --git a/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassMetadataIntrinsic.java b/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassMetadataIntrinsic.java index 82a4a7ea8..138a6a432 100644 --- a/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassMetadataIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassMetadataIntrinsic.java @@ -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; } } diff --git a/core/src/main/java/org/teavm/backend/wasm/intrinsics/PlatformClassMetadataIntrinsic.java b/core/src/main/java/org/teavm/backend/wasm/intrinsics/PlatformClassMetadataIntrinsic.java index 65ff99b94..c56d83c45 100644 --- a/core/src/main/java/org/teavm/backend/wasm/intrinsics/PlatformClassMetadataIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/wasm/intrinsics/PlatformClassMetadataIntrinsic.java @@ -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(); } diff --git a/core/src/main/java/org/teavm/runtime/RuntimeClass.java b/core/src/main/java/org/teavm/runtime/RuntimeClass.java index ae6fede67..45aa4afd5 100644 --- a/core/src/main/java/org/teavm/runtime/RuntimeClass.java +++ b/core/src/main/java/org/teavm/runtime/RuntimeClass.java @@ -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; diff --git a/tests/src/test/java/org/teavm/classlib/java/lang/ClassTest.java b/tests/src/test/java/org/teavm/classlib/java/lang/ClassTest.java index d5a983e68..44c8b2260 100644 --- a/tests/src/test/java/org/teavm/classlib/java/lang/ClassTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/lang/ClassTest.java @@ -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), diff --git a/tests/src/test/java/org/teavm/classlib/java/util/EnumMapTest.java b/tests/src/test/java/org/teavm/classlib/java/util/EnumMapTest.java index 64ff7b84b..e3b782925 100644 --- a/tests/src/test/java/org/teavm/classlib/java/util/EnumMapTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/util/EnumMapTest.java @@ -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); diff --git a/tests/src/test/java/org/teavm/classlib/java/util/EnumSetTest.java b/tests/src/test/java/org/teavm/classlib/java/util/EnumSetTest.java index 3166c38d9..8692eaa55 100644 --- a/tests/src/test/java/org/teavm/classlib/java/util/EnumSetTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/util/EnumSetTest.java @@ -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 set = EnumSet.noneOf(EnumFoo.class); set.add(EnumFoo.a);