diff --git a/classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassDependencyListener.java b/classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassDependencyListener.java new file mode 100644 index 000000000..d75a24c9b --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassDependencyListener.java @@ -0,0 +1,36 @@ +/* + * Copyright 2019 konsoletyper. + * + * 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.classlib.impl; + +import org.teavm.dependency.AbstractDependencyListener; +import org.teavm.dependency.DependencyAgent; +import org.teavm.dependency.MethodDependency; +import org.teavm.model.ClassReader; + +public class DeclaringClassDependencyListener extends AbstractDependencyListener { + @Override + public void methodReached(DependencyAgent agent, MethodDependency method) { + if (method.getReference().getClassName().equals("java.lang.Class") + && method.getReference().getName().equals("getDeclaringClass")) { + method.getVariable(0).getClassValueNode().addConsumer(t -> { + ClassReader cls = agent.getClassSource().get(t.getName()); + if (cls != null && cls.getOwnerName() != null) { + agent.linkClass(cls.getOwnerName()); + } + }); + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassGenerator.java b/classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassGenerator.java new file mode 100644 index 000000000..9be6ed519 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassGenerator.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 konsoletyper. + * + * 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.classlib.impl; + +import java.io.IOException; +import org.teavm.backend.javascript.codegen.SourceWriter; +import org.teavm.backend.javascript.spi.Generator; +import org.teavm.backend.javascript.spi.GeneratorContext; +import org.teavm.dependency.MethodDependencyInfo; +import org.teavm.model.ClassReader; +import org.teavm.model.MethodReference; + +public class DeclaringClassGenerator implements Generator { + private static final MethodReference METHOD = new MethodReference(Class.class, "getDeclaringClass", + Class.class); + + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { + writer.append("var p").ws().append("=").ws().append("\"teavm_declaredClass\";").softNewLine(); + writer.append("if").ws().append("(!").appendMethodBody(methodRef).append(".initialized").append(")") + .ws().append("{").indent().softNewLine(); + + MethodDependencyInfo methodDep = context.getDependency().getMethod(METHOD); + if (methodDep != null) { + for (String type : methodDep.getVariable(0).getClassValueNode().getTypes()) { + ClassReader cls = context.getClassSource().get(type); + if (cls != null) { + writer.appendClass(type).append("[p]").ws().append("=").ws(); + if (cls.getOwnerName() != null) { + writer.appendClass(cls.getOwnerName()); + } else { + writer.append("null"); + } + writer.append(";").softNewLine(); + } + } + } + + writer.appendMethodBody(methodRef).append(".initialized").ws().append("=").ws().append("true;").softNewLine(); + writer.outdent().append("}").softNewLine(); + writer.append("return ").append(context.getParameterName(1)).append("[p];").softNewLine(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassMetadataGenerator.java b/classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassMetadataGenerator.java deleted file mode 100644 index 0ea23c999..000000000 --- a/classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassMetadataGenerator.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 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.classlib.impl; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import org.teavm.model.ClassReader; -import org.teavm.model.MethodReference; -import org.teavm.platform.metadata.ClassScopedMetadataGenerator; -import org.teavm.platform.metadata.MetadataGeneratorContext; -import org.teavm.platform.metadata.Resource; - -public class DeclaringClassMetadataGenerator implements ClassScopedMetadataGenerator { - @Override - public Map generateMetadata(MetadataGeneratorContext context, - Collection classNames, MethodReference method) { - Map result = new HashMap<>(); - for (String clsName : classNames) { - ClassReader cls = context.getClassSource().get(clsName); - if (cls.getOwnerName() != null) { - result.put(clsName, context.createClassResource(cls.getOwnerName())); - } - } - return result; - } -} diff --git a/classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java b/classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java index 900ed3251..339266486 100644 --- a/classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java +++ b/classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java @@ -49,7 +49,6 @@ import org.teavm.interop.PlatformMarker; import org.teavm.model.MethodReference; import org.teavm.model.ValueType; import org.teavm.platform.PlatformClass; -import org.teavm.platform.metadata.ClassResource; import org.teavm.platform.metadata.ResourceArray; import org.teavm.platform.metadata.ResourceMap; import org.teavm.platform.metadata.StringResource; @@ -144,6 +143,13 @@ public class JCLPlugin implements TeaVMPlugin { TeaVMPluginUtil.handleNatives(host, Math.class); installMetadata(host.getService(MetadataRegistration.class)); + host.add(new DeclaringClassDependencyListener()); + + TeaVMJavaScriptHost jsExtension = host.getExtension(TeaVMJavaScriptHost.class); + if (jsExtension != null) { + jsExtension.add(new MethodReference(Class.class, "getDeclaringClassImpl", PlatformClass.class, + PlatformClass.class), new DeclaringClassGenerator()); + } } private void installMetadata(MetadataRegistration reg) { @@ -207,9 +213,6 @@ public class JCLPlugin implements TeaVMPlugin { new CharacterMetadataGenerator()); reg.register(new MethodReference(Character.class, "obtainClasses", StringResource.class), new CharacterMetadataGenerator()); - - reg.register(new MethodReference(Class.class, "getDeclaringClass", PlatformClass.class, ClassResource.class), - new DeclaringClassMetadataGenerator()); } @PlatformMarker diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java index 4689e6438..2ca247b4a 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java @@ -47,7 +47,6 @@ import org.teavm.jso.core.JSArray; import org.teavm.platform.Platform; import org.teavm.platform.PlatformClass; import org.teavm.platform.PlatformSequence; -import org.teavm.platform.metadata.ClassResource; import org.teavm.runtime.RuntimeClass; import org.teavm.runtime.RuntimeObject; @@ -598,11 +597,11 @@ public class TClass extends TObject implements TAnnotatedElement { } public TClass getDeclaringClass() { - ClassResource res = getDeclaringClass(platformClass); - return res != null ? getClass(Platform.classFromResource(res)) : null; + PlatformClass result = getDeclaringClassImpl(getPlatformClass()); + return result != null ? getClass(result) : null; } - - private static native ClassResource getDeclaringClass(PlatformClass cls); + + private static native PlatformClass getDeclaringClassImpl(PlatformClass cls); @SuppressWarnings("unchecked") public TClass asSubclass(TClass clazz) { diff --git a/platform/src/main/java/org/teavm/platform/Platform.java b/platform/src/main/java/org/teavm/platform/Platform.java index 45b50473b..e84bc5cbb 100644 --- a/platform/src/main/java/org/teavm/platform/Platform.java +++ b/platform/src/main/java/org/teavm/platform/Platform.java @@ -29,7 +29,6 @@ import org.teavm.jso.JSBody; import org.teavm.jso.JSObject; import org.teavm.jso.browser.Window; import org.teavm.jso.core.JSString; -import org.teavm.platform.metadata.ClassResource; import org.teavm.platform.metadata.StaticFieldResource; import org.teavm.platform.plugin.PlatformGenerator; import org.teavm.runtime.RuntimeClass; @@ -130,10 +129,6 @@ public final class Platform { } } - @InjectedBy(PlatformGenerator.class) - @PluggableDependency(PlatformGenerator.class) - public static native PlatformClass classFromResource(ClassResource resource); - @InjectedBy(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class) public static native Object objectFromResource(StaticFieldResource resource); diff --git a/platform/src/main/java/org/teavm/platform/metadata/ClassResource.java b/platform/src/main/java/org/teavm/platform/metadata/ClassResource.java deleted file mode 100644 index d7a40bfd9..000000000 --- a/platform/src/main/java/org/teavm/platform/metadata/ClassResource.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2015 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.platform.metadata; - -public interface ClassResource extends Resource { -} diff --git a/platform/src/main/java/org/teavm/platform/metadata/ClassScopedMetadataGenerator.java b/platform/src/main/java/org/teavm/platform/metadata/ClassScopedMetadataGenerator.java deleted file mode 100644 index a825f0c59..000000000 --- a/platform/src/main/java/org/teavm/platform/metadata/ClassScopedMetadataGenerator.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2015 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.platform.metadata; - -import java.util.Collection; -import java.util.Map; -import org.teavm.model.MethodReference; -import org.teavm.platform.PlatformClass; - -/** - *

Behaviour of this class is similar to {@link MetadataGenerator}. The difference is that method, marked with - * {@link ClassScopedMetadataProvider} must take one argument of type {@link PlatformClass}. It will - * return different resource for each given class, corresponding to map entries, produced by - * {@link #generateMetadata(MetadataGeneratorContext, Collection, MethodReference)}. - * - * @see ClassScopedMetadataProvider - * @see MetadataGenerator - * - * @author Alexey Andreev - */ -public interface ClassScopedMetadataGenerator { - Map generateMetadata(MetadataGeneratorContext context, Collection classNames, - MethodReference method); -} diff --git a/platform/src/main/java/org/teavm/platform/metadata/MetadataGeneratorContext.java b/platform/src/main/java/org/teavm/platform/metadata/MetadataGeneratorContext.java index 2078a92f3..1f33e24d4 100644 --- a/platform/src/main/java/org/teavm/platform/metadata/MetadataGeneratorContext.java +++ b/platform/src/main/java/org/teavm/platform/metadata/MetadataGeneratorContext.java @@ -59,15 +59,6 @@ public interface MetadataGeneratorContext extends ServiceRepository { */ T createResource(Class resourceType); - /** - * Creates a new resource that represents class literal. Client code then may use - * {@link Platform#classFromResource(ClassResource)} to get actual class. - * - * @param className class to which resource is to point. - * @return a new resource. - */ - ClassResource createClassResource(String className); - /** * Creates a new resource that represents static field. Client code then may use * {@link Platform#objectFromResource(StaticFieldResource)} to get actual field value. diff --git a/platform/src/main/java/org/teavm/platform/plugin/BuildTimeClassResource.java b/platform/src/main/java/org/teavm/platform/plugin/BuildTimeClassResource.java deleted file mode 100644 index f2d291157..000000000 --- a/platform/src/main/java/org/teavm/platform/plugin/BuildTimeClassResource.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2015 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.platform.plugin; - -import java.io.IOException; -import org.teavm.backend.javascript.codegen.SourceWriter; -import org.teavm.platform.metadata.ClassResource; - -class BuildTimeClassResource implements ClassResource, ResourceWriter { - private String className; - - public BuildTimeClassResource(String className) { - this.className = className; - } - - public String getClassName() { - return className; - } - - @Override - public void write(SourceWriter writer) throws IOException { - writer.appendClass(className); - } -} diff --git a/platform/src/main/java/org/teavm/platform/plugin/ClassScopedMetadataProviderNativeGenerator.java b/platform/src/main/java/org/teavm/platform/plugin/ClassScopedMetadataProviderNativeGenerator.java deleted file mode 100644 index dc3af6a78..000000000 --- a/platform/src/main/java/org/teavm/platform/plugin/ClassScopedMetadataProviderNativeGenerator.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2015 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.platform.plugin; - -import java.io.IOException; -import java.util.Map; -import org.teavm.backend.javascript.codegen.SourceWriter; -import org.teavm.backend.javascript.rendering.RenderingUtil; -import org.teavm.backend.javascript.spi.Generator; -import org.teavm.backend.javascript.spi.GeneratorContext; -import org.teavm.model.MethodReference; -import org.teavm.platform.metadata.ClassScopedMetadataGenerator; -import org.teavm.platform.metadata.Resource; - -class ClassScopedMetadataProviderNativeGenerator implements Generator { - private ClassScopedMetadataGenerator generator; - - ClassScopedMetadataProviderNativeGenerator(ClassScopedMetadataGenerator generator) { - this.generator = generator; - } - - @Override - public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { - DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(), - context.getClassLoader(), context.getProperties(), context); - - Map resourceMap = generator.generateMetadata(metadataContext, - context.getClassSource().getClassNames(), methodRef); - writer.append("var p").ws().append("=").ws().append("\"" + RenderingUtil.escapeString("$$res_" - + writer.getNaming().getFullNameFor(methodRef)) + "\"").append(";").softNewLine(); - for (Map.Entry entry : resourceMap.entrySet()) { - writer.appendClass(entry.getKey()).append("[p]").ws().append("=").ws(); - ResourceWriterHelper.write(writer, entry.getValue()); - writer.append(";").softNewLine(); - } - writer.appendMethodBody(methodRef).ws().append('=').ws().append("function(cls)").ws().append("{") - .softNewLine().indent(); - writer.append("return cls.hasOwnProperty(p)").ws().append("?").ws().append("cls[p]").ws().append(":") - .ws().append("null;").softNewLine(); - writer.outdent().append("};").softNewLine(); - writer.append("return ").appendMethodBody(methodRef).append("(").append(context.getParameterName(1)) - .append(");").softNewLine(); - } -} diff --git a/platform/src/main/java/org/teavm/platform/plugin/DefaultMetadataGeneratorContext.java b/platform/src/main/java/org/teavm/platform/plugin/DefaultMetadataGeneratorContext.java index 65724932d..802bede5a 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/DefaultMetadataGeneratorContext.java +++ b/platform/src/main/java/org/teavm/platform/plugin/DefaultMetadataGeneratorContext.java @@ -20,7 +20,6 @@ import java.util.Properties; import org.teavm.common.ServiceRepository; import org.teavm.model.ClassReaderSource; import org.teavm.model.FieldReference; -import org.teavm.platform.metadata.ClassResource; import org.teavm.platform.metadata.MetadataGeneratorContext; import org.teavm.platform.metadata.Resource; import org.teavm.platform.metadata.ResourceArray; @@ -81,11 +80,6 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext { return new BuildTimeResourceArray<>(); } - @Override - public ClassResource createClassResource(String className) { - return new BuildTimeClassResource(className); - } - @Override public StaticFieldResource createFieldResource(FieldReference field) { return new BuildTimeStaticFieldResource(field); diff --git a/platform/src/main/java/org/teavm/platform/plugin/MetadataRegistration.java b/platform/src/main/java/org/teavm/platform/plugin/MetadataRegistration.java index 4a1dc72ab..8da89b1c1 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/MetadataRegistration.java +++ b/platform/src/main/java/org/teavm/platform/plugin/MetadataRegistration.java @@ -16,11 +16,8 @@ package org.teavm.platform.plugin; import org.teavm.model.MethodReference; -import org.teavm.platform.metadata.ClassScopedMetadataGenerator; import org.teavm.platform.metadata.MetadataGenerator; public interface MetadataRegistration { void register(MethodReference method, MetadataGenerator generator); - - void register(MethodReference method, ClassScopedMetadataGenerator generator); } diff --git a/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java b/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java index 1339c3663..fd6f8d7d9 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java +++ b/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java @@ -17,7 +17,6 @@ package org.teavm.platform.plugin; import java.util.ArrayList; import java.util.List; -import java.util.function.BiConsumer; import org.teavm.ast.InvocationExpr; import org.teavm.backend.c.TeaVMCHost; import org.teavm.backend.c.intrinsic.Intrinsic; @@ -34,7 +33,6 @@ import org.teavm.model.MethodReader; import org.teavm.model.MethodReference; import org.teavm.platform.Platform; import org.teavm.platform.PlatformQueue; -import org.teavm.platform.metadata.ClassScopedMetadataGenerator; import org.teavm.platform.metadata.MetadataGenerator; import org.teavm.vm.TeaVMPluginUtil; import org.teavm.vm.spi.TeaVMHost; @@ -43,8 +41,6 @@ import org.teavm.vm.spi.TeaVMPlugin; public class PlatformPlugin implements TeaVMPlugin, MetadataRegistration { private MetadataProviderTransformer metadataTransformer = new MetadataProviderTransformer(); private List metadataGeneratorConsumers = new ArrayList<>(); - private List> scopedMetadataGeneratorConsumers - = new ArrayList<>(); @Override public void install(TeaVMHost host) { @@ -71,8 +67,6 @@ public class PlatformPlugin implements TeaVMPlugin, MetadataRegistration { metadataGeneratorConsumers.add((method, constructor, generator) -> jsHost.add(method, new MetadataProviderNativeGenerator(generator, constructor))); - scopedMetadataGeneratorConsumers.add((method, generator) -> jsHost.add(method, - new ClassScopedMetadataProviderNativeGenerator(generator))); } else if (!isBootstrap()) { host.add(new StringAmplifierTransformer()); } @@ -149,13 +143,6 @@ public class PlatformPlugin implements TeaVMPlugin, MetadataRegistration { metadataTransformer.addMetadataMethod(method); } - @Override - public void register(MethodReference method, ClassScopedMetadataGenerator generator) { - for (BiConsumer consumer : scopedMetadataGeneratorConsumers) { - consumer.accept(method, generator); - } - } - interface MetadataGeneratorConsumer { void consume(MethodReference constructor, MethodReference target, MetadataGenerator generator); }