Start eliminating JavaScript generators in classlib in favour of calling

Platform and JSO
This commit is contained in:
konsoletyper 2015-02-07 20:58:47 +04:00
parent 3b1d6851a4
commit d93fa6cf41
21 changed files with 592 additions and 202 deletions

View File

@ -0,0 +1,32 @@
/*
* 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 org.teavm.model.MethodReference;
import org.teavm.platform.metadata.MetadataGenerator;
import org.teavm.platform.metadata.MetadataGeneratorContext;
import org.teavm.platform.metadata.Resource;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class DeclaringClassMetadataGenerator implements MetadataGenerator {
@Override
public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) {
return null;
}
}

View File

@ -31,7 +31,6 @@ public class JCLPlugin implements TeaVMPlugin {
host.add(new EnumDependencySupport());
host.add(new EnumTransformer());
host.add(new ClassLookupDependencySupport());
host.add(new NewInstanceDependencySupport());
host.add(new ObjectEnrichRenderer());
ServiceLoaderSupport serviceLoaderSupp = new ServiceLoaderSupport(host.getClassLoader());
host.add(serviceLoaderSupp);

View File

@ -35,75 +35,18 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
throws IOException {
switch (methodRef.getName()) {
case "getComponentType0":
generateGetComponentType(context, writer);
break;
case "getSuperclass":
generateGetSuperclass(context, writer);
break;
case "forNameImpl":
generateForName(context, writer);
break;
case "newInstance":
generateNewInstance(context, writer);
break;
case "getDeclaringClass":
generateGetDeclaringClass(context, writer);
break;
}
}
private void generateGetComponentType(GeneratorContext context, SourceWriter writer) throws IOException {
String thisArg = context.getParameterName(0);
writer.append("var item = " + thisArg + ".$data.$meta.item;").softNewLine();
writer.append("return item != null ? $rt_cls(item) : null;").softNewLine();
}
private void generateGetSuperclass(GeneratorContext context, SourceWriter writer) throws IOException {
String thisArg = context.getParameterName(0);
writer.append("var superclass = " + thisArg + ".$data.$meta.superclass;").softNewLine();
writer.append("return superclass ? $rt_cls(superclass) : null;").softNewLine();
}
@Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
switch (methodRef.getName()) {
case "isInstance":
generateIsInstance(context);
break;
case "isAssignableFrom":
generateIsAssignableFrom(context);
break;
case "voidClass":
context.getWriter().append("$rt_cls($rt_voidcls())");
break;
case "booleanClass":
context.getWriter().append("$rt_cls($rt_booleancls())");
break;
case "charClass":
context.getWriter().append("$rt_cls($rt_charcls())");
break;
case "byteClass":
context.getWriter().append("$rt_cls($rt_bytecls())");
break;
case "shortClass":
context.getWriter().append("$rt_cls($rt_shortcls())");
break;
case "intClass":
context.getWriter().append("$rt_cls($rt_intcls())");
break;
case "longClass":
context.getWriter().append("$rt_cls($rt_longcls())");
break;
case "floatClass":
context.getWriter().append("$rt_cls($rt_floatcls())");
break;
case "doubleClass":
context.getWriter().append("$rt_cls($rt_doublecls())");
break;
case "wrapClass":
context.writeExpr(context.getArgument(0));
break;
case "getEnumConstantsImpl":
context.writeExpr(context.getArgument(0));
context.getWriter().append(".$data.values()");
@ -111,24 +54,6 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
}
}
private void generateIsAssignableFrom(InjectorContext context) throws IOException {
SourceWriter writer = context.getWriter();
writer.append("$rt_isAssignable(");
context.writeExpr(context.getArgument(1));
writer.append(".$data,").ws();
context.writeExpr(context.getArgument(0));
writer.append(".$data)");
}
private void generateIsInstance(InjectorContext context) throws IOException {
SourceWriter writer = context.getWriter();
writer.append("$rt_isInstance(");
context.writeExpr(context.getArgument(1));
writer.append(",").ws();
context.writeExpr(context.getArgument(0));
writer.append(".$data)");
}
private void generateForName(GeneratorContext context, SourceWriter writer) throws IOException {
String param = context.getParameterName(1);
writer.append("switch ($rt_ustr(" + param + ")) {").softNewLine().indent();
@ -140,32 +65,6 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
writer.outdent().append("}").softNewLine();
}
private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException {
String self = context.getParameterName(0);
writer.append("if (!").appendClass("java.lang.Class").append(".$$constructors$$) {").indent().softNewLine();
writer.appendClass("java.lang.Class").append(".$$constructors$$ = true;").softNewLine();
for (String clsName : context.getClassSource().getClassNames()) {
ClassReader cls = context.getClassSource().get(clsName);
MethodReader method = cls.getMethod(new MethodDescriptor("<init>", ValueType.VOID));
if (method != null) {
writer.appendClass(clsName).append(".$$constructor$$ = ").appendMethodBody(method.getReference())
.append(";").softNewLine();
}
}
writer.outdent().append("}").softNewLine();
writer.append("var cls = " + self + ".$data;").softNewLine();
writer.append("var ctor = cls.$$constructor$$;").softNewLine();
writer.append("if (!ctor) {").indent().softNewLine();
writer.append("var ex = new ").appendClass(InstantiationException.class.getName()).append("();").softNewLine();
writer.appendMethodBody(new MethodReference(InstantiationException.class.getName(), new MethodDescriptor(
"<init>", ValueType.VOID))).append("(ex);").softNewLine();
writer.append("$rt_throw(ex);").softNewLine();
writer.outdent().append("}").softNewLine();
writer.append("var instance = new cls();").softNewLine();
writer.append("ctor(instance);").softNewLine();
writer.append("return instance;").softNewLine();
}
private void generateGetDeclaringClass(GeneratorContext context, SourceWriter writer) throws IOException {
String self = context.getParameterName(0);
writer.append("if (!").appendClass("java.lang.Class").append(".$$owners$$) {").indent().softNewLine();
@ -188,25 +87,10 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
@Override
public void methodAchieved(DependencyAgent agent, MethodDependency graph, CallLocation location) {
switch (graph.getReference().getName()) {
case "voidClass":
case "booleanClass":
case "byteClass":
case "shortClass":
case "charClass":
case "intClass":
case "longClass":
case "floatClass":
case "doubleClass":
case "wrapClass":
case "getSuperclass":
case "getComponentType0":
case "forNameImpl":
case "getDeclaringClass":
graph.getResult().propagate(agent.getType("java.lang.Class"));
break;
case "getName":
graph.getResult().propagate(agent.getType("java.lang.String"));
break;
case "newInstance":
agent.linkMethod(new MethodReference(InstantiationException.class, "<init>", void.class),
location).use();

View File

@ -15,9 +15,11 @@
*/
package org.teavm.classlib.java.lang;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.spi.GeneratedBy;
import org.teavm.classlib.impl.DeclaringClassMetadataGenerator;
import org.teavm.javascript.spi.InjectedBy;
import org.teavm.platform.Platform;
import org.teavm.platform.PlatformClass;
import org.teavm.platform.metadata.MetadataProvider;
/**
*
@ -25,102 +27,122 @@ import org.teavm.javascript.spi.InjectedBy;
*/
public class TClass<T> extends TObject {
TString name;
TString binaryName;
boolean primitive;
boolean array;
boolean isEnum;
private TClass<?> componentType;
private boolean componentTypeDirty = true;
private PlatformClass platformClass;
static TClass<?> createNew() {
return new TClass<>();
private TClass(PlatformClass platformClass) {
this.platformClass = platformClass;
platformClass.setJavaClass(Platform.getPlatformObject(this));
}
@InjectedBy(ClassNativeGenerator.class)
public native boolean isInstance(TObject obj);
static TClass<?> getClass(PlatformClass cls) {
if (cls == null) {
return null;
}
TClass<?> result = (TClass<?>)(Object)Platform.asJavaClass(cls.getJavaClass());
if (result == null) {
result = new TClass<>(cls);
}
return result;
}
@InjectedBy(ClassNativeGenerator.class)
public native boolean isAssignableFrom(TClass<?> obj);
PlatformClass getPlatformClass() {
return platformClass;
}
public boolean isInstance(TObject obj) {
return Platform.isInstance(Platform.getPlatformObject(obj), platformClass);
}
public boolean isAssignableFrom(TClass<?> obj) {
return Platform.isAssignable(obj.getPlatformClass(), platformClass);
}
@PluggableDependency(ClassNativeGenerator.class)
public TString getName() {
if (name == null) {
name = TString.wrap(platformClass.getMetadata().getName());
}
return name;
}
public boolean isPrimitive() {
return primitive;
return platformClass.getMetadata().isPrimitive();
}
public boolean isArray() {
return array;
return platformClass.getMetadata().isArray();
}
public boolean isEnum() {
return isEnum;
return platformClass.getMetadata().isEnum();
}
public TClass<?> getComponentType() {
if (componentTypeDirty) {
componentType = getComponentType0();
PlatformClass arrayItem = platformClass.getMetadata().getArrayItem();
componentType = arrayItem != null ? getClass(arrayItem) : null;
componentTypeDirty = false;
}
return componentType;
}
@GeneratedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
private native TClass<?> getComponentType0();
@SuppressWarnings("unchecked")
static TClass<TVoid> voidClass() {
return (TClass<TVoid>)getClass(Platform.getPrimitives().getVoidClass());
}
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TVoid> voidClass();
@SuppressWarnings("unchecked")
static TClass<TBoolean> booleanClass() {
return (TClass<TBoolean>)getClass(Platform.getPrimitives().getBooleanClass());
}
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TBoolean> booleanClass();
@SuppressWarnings("unchecked")
static TClass<TCharacter> charClass() {
return (TClass<TCharacter>)getClass(Platform.getPrimitives().getCharClass());
}
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TCharacter> charClass();
@SuppressWarnings("unchecked")
static TClass<TByte> byteClass() {
return (TClass<TByte>)getClass(Platform.getPrimitives().getByteClass());
}
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TByte> byteClass();
@SuppressWarnings("unchecked")
static TClass<TShort> shortClass() {
return (TClass<TShort>)getClass(Platform.getPrimitives().getShortClass());
}
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TShort> shortClass();
@SuppressWarnings("unchecked")
static TClass<TInteger> intClass() {
return (TClass<TInteger>)getClass(Platform.getPrimitives().getIntClass());
}
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TInteger> intClass();
@SuppressWarnings("unchecked")
static TClass<TLong> longClass() {
return (TClass<TLong>)getClass(Platform.getPrimitives().getLongClass());
}
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TLong> longClass();
@SuppressWarnings("unchecked")
static TClass<TFloat> floatClass() {
return (TClass<TFloat>)getClass(Platform.getPrimitives().getFloatClass());
}
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TFloat> floatClass();
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TDouble> doubleClass();
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
public static native <S extends TObject> TClass<S> wrapClass(Class<S> cls);
@SuppressWarnings("unchecked")
static TClass<TDouble> doubleClass() {
return (TClass<TDouble>)getClass(Platform.getPrimitives().getDoubleClass());
}
public boolean desiredAssertionStatus() {
return true;
}
@GeneratedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
public native TClass<? super T> getSuperclass();
@SuppressWarnings("unchecked")
public TClass<? super T> getSuperclass() {
return (TClass<? super T>)getClass(platformClass.getMetadata().getSuperclass());
}
public T[] getEnumConstants() {
return isEnum ? getEnumConstantsImpl() : null;
return isEnum() ? getEnumConstantsImpl() : null;
}
@InjectedBy(ClassNativeGenerator.class)
@ -128,10 +150,9 @@ public class TClass<T> extends TObject {
@SuppressWarnings("unchecked")
public T cast(TObject obj) {
if (obj != null && !isAssignableFrom(TClass.wrapClass(obj.getClass()))) {
throw new TClassCastException(TString.wrap(new TStringBuilder()
.append(TClass.wrapClass(obj.getClass()).getName())
.append(TString.wrap(" is not subtype of ")).append(name).toString()));
if (obj != null && !isAssignableFrom((TClass<?>)(Object)obj.getClass())) {
throw new TClassCastException(TString.wrap(obj.getClass().getName() +
" is not subtype of " + name));
}
return (T)obj;
}
@ -140,30 +161,25 @@ public class TClass<T> extends TObject {
return TClassLoader.getSystemClassLoader();
}
@GeneratedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
private static native TClass<?> forNameImpl(TString name);
public static TClass<?> forName(TString name) throws TClassNotFoundException {
TClass<?> result = forNameImpl(name);
if (result == null) {
PlatformClass cls = Platform.lookupClass(name.toString());
if (cls == null) {
throw new TClassNotFoundException();
}
return result;
return getClass(cls);
}
@SuppressWarnings("unused")
public static TClass<?> forName(TString name, boolean initialize, TClassLoader loader)
throws TClassNotFoundException {
throws TClassNotFoundException {
return forName(name);
}
@GeneratedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
public native T newInstance() throws TInstantiationException, TIllegalAccessException;
public T newInstance() throws TInstantiationException, TIllegalAccessException {
return Platform.newInstance(platformClass);
}
@GeneratedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
@MetadataProvider(DeclaringClassMetadataGenerator.class)
public native TClass<?> getDeclaringClass();
@SuppressWarnings("unchecked")

View File

@ -61,7 +61,7 @@ public abstract class TEnum<E extends TEnum<E>> extends TObject implements TComp
@SuppressWarnings("unchecked")
public final TClass<E> getDeclaringClass() {
return (TClass<E>)TClass.wrapClass(getClass());
return (TClass<E>)(Object)getClass();
}
@Override

View File

@ -103,6 +103,10 @@ public class SourceWriter implements Appendable, LocationProvider {
return append(naming.getNameFor(cls));
}
public SourceWriter appendClass(Class<?> cls) throws NamingException, IOException {
return append(naming.getNameFor(cls.getName()));
}
public SourceWriter appendField(FieldReference field) throws NamingException, IOException {
return append(naming.getNameFor(field));
}
@ -113,7 +117,12 @@ public class SourceWriter implements Appendable, LocationProvider {
public SourceWriter appendMethod(String className, String name, ValueType... params)
throws NamingException, IOException {
return append(naming.getNameFor(new MethodReference(className, new MethodDescriptor(name, params))));
return append(naming.getNameFor(new MethodReference(className, name, params)));
}
public SourceWriter appendMethod(Class<?> cls, String name, Class<?>... params)
throws NamingException, IOException {
return append(naming.getNameFor(new MethodReference(cls, name, params)));
}
public SourceWriter appendMethodBody(MethodReference method) throws NamingException, IOException {
@ -125,6 +134,11 @@ public class SourceWriter implements Appendable, LocationProvider {
return append(naming.getFullNameFor(new MethodReference(className, new MethodDescriptor(name, params))));
}
public SourceWriter appendMethodBody(Class<?> cls, String name, Class<?>... params)
throws NamingException, IOException {
return append(naming.getFullNameFor(new MethodReference(cls, name, params)));
}
private void appendIndent() throws IOException {
if (minified) {
return;

View File

@ -102,7 +102,7 @@ public final class JS {
public static native JSObject wrap(short num);
@InjectedBy(JSNativeGenerator.class)
public static native JSObject pass(Object obj);
public static native JSObject marshall(Object obj);
public static <T extends JSObject> JSArray<T> wrap(T[] array) {
JSArray<T> result = createArray(array.length);

View File

@ -35,6 +35,16 @@
<artifactId>teavm-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-jso</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-dom</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View File

@ -0,0 +1,78 @@
/*
* 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;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.spi.GeneratedBy;
import org.teavm.javascript.spi.InjectedBy;
import org.teavm.jso.JS;
import org.teavm.platform.metadata.ClassResource;
import org.teavm.platform.plugin.PlatformGenerator;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public final class Platform {
private Platform() {
}
public static PlatformObject getPlatformObject(Object obj) {
return (PlatformObject)JS.marshall(obj);
}
public static boolean isInstance(PlatformObject obj, PlatformClass cls) {
return obj != null && !JS.isUndefined(obj.getPlatformClass().getMetadata()) &&
isAssignable(obj.getPlatformClass(), cls);
}
public static boolean isAssignable(PlatformClass from, PlatformClass to) {
if (from == to) {
return true;
}
PlatformSequence<PlatformClass> supertypes = from.getMetadata().getSupertypes();
for (int i = 0; i < supertypes.getLength(); ++i) {
if (isAssignable(supertypes.get(i), to)) {
return true;
}
}
return false;
}
@InjectedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
public static native Class<?> asJavaClass(PlatformObject obj);
public static PlatformPrimitives getPrimitives() {
return (PlatformPrimitives)JS.getGlobal();
}
@GeneratedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
public static native <T> T newInstance(PlatformClass cls);
@GeneratedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
public static native PlatformClass lookupClass(String name);
@GeneratedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
public static native void initClass(PlatformClass cls);
@GeneratedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
public static native PlatformClass classFromResource(ClassResource resource);
}

View File

@ -0,0 +1,35 @@
/*
* 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;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty;
import org.teavm.platform.metadata.Resource;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface PlatformClass extends JSObject, Resource {
@JSProperty("$meta")
PlatformClassMetadata getMetadata();
@JSProperty("classObject")
void setJavaClass(PlatformObject obj);
@JSProperty("classObject")
PlatformObject getJavaClass();
}

View File

@ -0,0 +1,46 @@
/*
* 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;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface PlatformClassMetadata extends JSObject {
@JSProperty("item")
PlatformClass getArrayItem();
@JSProperty
PlatformSequence<PlatformClass> getSupertypes();
@JSProperty
PlatformClass getSuperclass();
@JSProperty
String getName();
@JSProperty
boolean isPrimitive();
@JSProperty
boolean isArray();
@JSProperty
boolean isEnum();
}

View File

@ -0,0 +1,28 @@
/*
* 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;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface PlatformObject extends JSObject {
@JSProperty("constructor")
PlatformClass getPlatformClass();
}

View File

@ -0,0 +1,52 @@
/*
* 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;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface PlatformPrimitives extends JSObject {
@JSProperty("$rt_voidcls")
PlatformClass getVoidClass();
@JSProperty("$rt_booleancls")
PlatformClass getBooleanClass();
@JSProperty("$rt_bytecls")
PlatformClass getByteClass();
@JSProperty("$rt_shortcls")
PlatformClass getShortClass();
@JSProperty("$rt_charcls")
PlatformClass getCharClass();
@JSProperty("$rt_intcls")
PlatformClass getIntClass();
@JSProperty("$rt_longcls")
PlatformClass getLongClass();
@JSProperty("$rt_floatcls")
PlatformClass getFloatClass();
@JSProperty("$rt_doublecls")
PlatformClass getDoubleClass();
}

View File

@ -0,0 +1,32 @@
/*
* 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;
import org.teavm.jso.JSIndexer;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface PlatformSequence<T> extends JSObject {
@JSProperty
int getLength();
@JSIndexer
T get(int index);
}

View File

@ -0,0 +1,23 @@
/*
* 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;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface ClassResource extends Resource {
}

View File

@ -18,6 +18,7 @@ package org.teavm.platform.metadata;
import java.util.Properties;
import org.teavm.common.ServiceRepository;
import org.teavm.model.ListableClassReaderSource;
import org.teavm.platform.Platform;
import org.teavm.vm.TeaVM;
/**
@ -48,6 +49,12 @@ public interface MetadataGeneratorContext extends ServiceRepository {
*/
<T extends Resource> T createResource(Class<T> resourceType);
/**
* Creates a new resource that represents class literal. Client code then may use
* {@link Platform#classFromResource(ClassResource)} to get actual class.
*/
ClassResource createClassResource(String className);
/**
* Creates a new resource array.
*/

View File

@ -0,0 +1,41 @@
/*
* 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.codegen.SourceWriter;
import org.teavm.platform.metadata.ClassResource;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
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);
}
}

View File

@ -19,10 +19,7 @@ import java.lang.reflect.Proxy;
import java.util.Properties;
import org.teavm.common.ServiceRepository;
import org.teavm.model.ListableClassReaderSource;
import org.teavm.platform.metadata.MetadataGeneratorContext;
import org.teavm.platform.metadata.Resource;
import org.teavm.platform.metadata.ResourceArray;
import org.teavm.platform.metadata.ResourceMap;
import org.teavm.platform.metadata.*;
/**
*
@ -70,6 +67,11 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
return new BuildTimeResourceArray<>();
}
@Override
public ClassResource createClassResource(String className) {
return new BuildTimeClassResource(className);
}
@Override
public <T extends Resource> ResourceMap<T> createResourceMap() {
return new BuildTimeResourceMap<>();

View File

@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.impl;
package org.teavm.platform.plugin;
import org.teavm.dependency.*;
import org.teavm.model.*;
import org.teavm.platform.Platform;
/**
*
@ -39,7 +40,7 @@ public class NewInstanceDependencySupport implements DependencyListener {
if (cls.hasModifier(ElementModifier.ABSTRACT) || cls.hasModifier(ElementModifier.INTERFACE)) {
return;
}
MethodReader method = cls.getMethod(new MethodDescriptor("<init>", ValueType.VOID));
MethodReader method = cls.getMethod(new MethodDescriptor("<init>", void.class));
if (method != null) {
allClassesNode.propagate(agent.getType(className));
}
@ -48,7 +49,7 @@ public class NewInstanceDependencySupport implements DependencyListener {
@Override
public void methodAchieved(final DependencyAgent agent, MethodDependency method, final CallLocation location) {
MethodReader reader = method.getMethod();
if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) {
if (reader.getOwnerName().equals(Platform.class.getName()) && reader.getName().equals("newInstance")) {
allClassesNode.connect(method.getResult());
method.getResult().addConsumer(new DependencyConsumer() {
@Override public void consume(DependencyAgentType type) {
@ -59,8 +60,10 @@ public class NewInstanceDependencySupport implements DependencyListener {
}
private void attachConstructor(DependencyAgent checker, String type, CallLocation location) {
MethodReference ref = new MethodReference(type, new MethodDescriptor("<init>", ValueType.VOID));
checker.linkMethod(ref, location).use();
MethodReference ref = new MethodReference(type, "<init>", ValueType.VOID);
MethodDependency methodDep = checker.linkMethod(ref, location);
methodDep.getVariable(0).propagate(checker.getType(type));
methodDep.use();
}
@Override

View File

@ -0,0 +1,87 @@
/*
* 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.codegen.SourceWriter;
import org.teavm.dependency.DependencyAgent;
import org.teavm.dependency.DependencyPlugin;
import org.teavm.dependency.MethodDependency;
import org.teavm.javascript.spi.Generator;
import org.teavm.javascript.spi.GeneratorContext;
import org.teavm.javascript.spi.Injector;
import org.teavm.javascript.spi.InjectorContext;
import org.teavm.model.*;
import org.teavm.platform.Platform;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class PlatformGenerator implements Generator, Injector, DependencyPlugin {
@Override
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
switch (method.getReference().getName()) {
case "asJavaClass":
method.getResult().propagate(agent.getType("java.lang.Class"));
return;
}
}
@Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
switch (methodRef.getName()) {
case "asJavaClass":
context.writeExpr(context.getArgument(0));
return;
}
}
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
switch (methodRef.getName()) {
case "newInstance":
generateNewInstance(context, writer);
}
}
private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException {
String self = context.getParameterName(0);
writer.append("if").ws().append("(!").appendClass(Platform.class).append(".$$constructors$$)").ws()
.append("{").indent().softNewLine();
writer.appendClass(Platform.class).append(".$$constructors$$").ws().append("=").append("true;").softNewLine();
for (String clsName : context.getClassSource().getClassNames()) {
ClassReader cls = context.getClassSource().get(clsName);
MethodReader method = cls.getMethod(new MethodDescriptor("<init>", void.class));
if (method != null) {
writer.appendClass(clsName).append(".$$constructor$$").ws().append("=").ws()
.appendMethodBody(method.getReference()).append(";").softNewLine();
}
}
writer.outdent().append("}").softNewLine();
writer.append("var cls = " + self + ".$data;").softNewLine();
writer.append("var ctor = cls.$$constructor$$;").softNewLine();
writer.append("if (!ctor) {").indent().softNewLine();
writer.append("var ex = new ").appendClass(InstantiationException.class.getName()).append("();").softNewLine();
writer.appendMethodBody(new MethodReference(InstantiationException.class, "<init>", void.class))
.append("(ex);").softNewLine();
writer.append("$rt_throw(ex);").softNewLine();
writer.outdent().append("}").softNewLine();
writer.append("var instance = new cls();").softNewLine();
writer.append("ctor(instance);").softNewLine();
writer.append("return instance;").softNewLine();
}
}

View File

@ -30,5 +30,6 @@ public class PlatformPlugin implements TeaVMPlugin {
host.add(new ResourceAccessorTransformer(host));
host.add(new ResourceAccessorDependencyListener());
host.add(new AsyncMethodProcessor());
host.add(new NewInstanceDependencySupport());
}
}