WASM: fix metadata intrinsics

This commit is contained in:
Alexey Andreev 2017-04-17 00:09:00 +03:00
parent 9e6061c3f1
commit f347de44a9
11 changed files with 156 additions and 36 deletions

View File

@ -20,10 +20,6 @@ import java.util.Arrays;
import org.teavm.classlib.impl.Base46;
import org.teavm.classlib.impl.CharFlow;
/**
*
* @author Alexey Andreev
*/
public final class UnicodeHelper {
private UnicodeHelper() {
}

View File

@ -26,7 +26,6 @@ public final class Example {
}
public static void main(String[] args) {
System.out.println(Integer.parseInt("123"));
testFibonacci();
testClasses();
testVirtualCall();
@ -39,7 +38,7 @@ public final class Example {
testArrayIsObject();
testIsAssignableFrom();
testExceptions();
//testBigInteger();
testBigInteger();
testGC();
}

View File

@ -72,7 +72,7 @@ public class BinaryWriter {
}
}
private static int align(int address, int alignment) {
public static int align(int address, int alignment) {
if (address == 0) {
return 0;
}

View File

@ -406,7 +406,7 @@ public class WasmClassGenerator {
data.cls = cls;
for (FieldReader field : cls.getFields()) {
int desiredAlignment = getDesiredAlignment(field.getType());
int desiredAlignment = getTypeSize(field.getType());
if (field.hasModifier(ElementModifier.STATIC)) {
DataType type = asDataType(field.getType());
data.fieldLayout.put(field.getName(), binaryWriter.append(type.createValue()));
@ -450,7 +450,7 @@ public class WasmClassGenerator {
return ((base - 1) / alignment + 1) * alignment;
}
private int getDesiredAlignment(ValueType type) {
public static int getTypeSize(ValueType type) {
if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive) type).getKind()) {
case BOOLEAN:

View File

@ -95,7 +95,7 @@ class BuildTimeResourceProxyBuilder {
methods.put(method, (proxy, args) -> descriptor);
break;
case "getValues":
methods.put(method, (proxy, args) -> initialData.clone());
methods.put(method, (proxy, args) -> proxy.data.clone());
break;
case "getPropertyIndex":
methods.put(method, (proxy, args) -> propertyIndexes.getOrDefault(args[0], -1));

View File

@ -15,10 +15,6 @@
*/
package org.teavm.platform.plugin;
/**
*
* @author Alexey Andreev
*/
class BuildTimeResourceSetter implements BuildTimeResourceMethod {
private int index;

View File

@ -15,8 +15,13 @@
*/
package org.teavm.platform.plugin;
import org.teavm.ast.InvocationExpr;
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
import org.teavm.backend.wasm.TeaVMWasmHost;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsic;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsicManager;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.model.MethodReference;
import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin;
@ -28,6 +33,8 @@ public class PlatformPlugin implements TeaVMPlugin {
host.add(new ResourceTransformer());
host.add(new ResourceAccessorTransformer(host));
host.add(new ResourceAccessorDependencyListener());
} else {
host.add(new StringAmplifierTransformer());
}
TeaVMWasmHost wasmHost = host.getExtension(TeaVMWasmHost.class);
@ -35,6 +42,18 @@ public class PlatformPlugin implements TeaVMPlugin {
wasmHost.add(ctx -> new MetadataIntrinsic(ctx.getClassSource(), ctx.getClassLoader(), ctx.getServices(),
ctx.getProperties()));
wasmHost.add(ctx -> new ResourceReadIntrinsic(ctx.getClassSource(), ctx.getClassLoader()));
wasmHost.add(ctx -> new WasmIntrinsic() {
@Override
public boolean isApplicable(MethodReference methodReference) {
return methodReference.getClassName().equals(StringAmplifier.class.getName());
}
@Override
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
return manager.generate(invocation.getArguments().get(0));
}
});
}
host.add(new AsyncMethodProcessor());

View File

@ -21,6 +21,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.teavm.ast.InvocationExpr;
import org.teavm.backend.wasm.binary.BinaryWriter;
import org.teavm.backend.wasm.generate.WasmClassGenerator;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsic;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsicManager;
import org.teavm.backend.wasm.model.expression.WasmExpression;
@ -119,8 +121,8 @@ public class ResourceReadIntrinsic implements WasmIntrinsic {
for (Method method : methods) {
MethodReference methodRef = MethodReference.parse(method);
ValueType propertyType = methodRef.getReturnType();
int size = getPropertySize(propertyType);
currentOffset = ((currentOffset + size - 1) / size + 1) * size;
int size = WasmClassGenerator.getTypeSize(propertyType);
currentOffset = BinaryWriter.align(currentOffset, size);
PropertyDescriptor propertyDescriptor = new PropertyDescriptor();
propertyDescriptor.offset = currentOffset;
@ -131,26 +133,6 @@ public class ResourceReadIntrinsic implements WasmIntrinsic {
}
}
private int getPropertySize(ValueType type) {
if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive) type).getKind()) {
case BOOLEAN:
case BYTE:
return 1;
case SHORT:
case CHARACTER:
return 2;
case INTEGER:
case FLOAT:
return 4;
case LONG:
case DOUBLE:
return 8;
}
}
return 4;
}
static class StructureDescriptor {
ResourceTypeDescriptor typeDescriptor;
Map<MethodReference, PropertyDescriptor> layout = new HashMap<>();

View File

@ -0,0 +1,26 @@
/*
* Copyright 2017 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 org.teavm.dependency.PluggableDependency;
final class StringAmplifier {
private StringAmplifier() {
}
@PluggableDependency(StringAmplifierDependencyPlugin.class)
static native String amplify(String string);
}

View File

@ -0,0 +1,28 @@
/*
* Copyright 2017 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 org.teavm.dependency.DependencyAgent;
import org.teavm.dependency.DependencyPlugin;
import org.teavm.dependency.MethodDependency;
import org.teavm.model.CallLocation;
public class StringAmplifierDependencyPlugin implements DependencyPlugin {
@Override
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
method.getResult().propagate(agent.getType("java.lang.String"));
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 2017 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 org.teavm.diagnostics.Diagnostics;
import org.teavm.model.BasicBlock;
import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.ClassReaderSource;
import org.teavm.model.Instruction;
import org.teavm.model.MethodHolder;
import org.teavm.model.MethodReference;
import org.teavm.model.Program;
import org.teavm.model.Variable;
import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.platform.metadata.Resource;
public class StringAmplifierTransformer implements ClassHolderTransformer {
@Override
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
for (MethodHolder method : cls.getMethods()) {
if (method.getProgram() != null) {
transformProgram(innerSource, method.getProgram());
}
}
}
private void transformProgram(ClassReaderSource classSource, Program program) {
for (BasicBlock block : program.getBasicBlocks()) {
for (Instruction instruction : block) {
if (!(instruction instanceof InvokeInstruction)) {
continue;
}
InvokeInstruction invoke = (InvokeInstruction) instruction;
if (invoke.getReceiver() == null) {
continue;
}
MethodReference method = invoke.getMethod();
String owningClass = method.getClassName();
if (classSource.isSuperType(Resource.class.getName(), owningClass).orElse(false)) {
if (method.getReturnType().isObject(String.class)) {
Variable var = program.createVariable();
InvokeInstruction amplifyInstruction = new InvokeInstruction();
amplifyInstruction.setMethod(new MethodReference(StringAmplifier.class, "amplify",
String.class, String.class));
amplifyInstruction.setType(InvocationType.SPECIAL);
amplifyInstruction.getArguments().add(var);
amplifyInstruction.setReceiver(invoke.getReceiver());
amplifyInstruction.setLocation(invoke.getLocation());
invoke.setReceiver(var);
invoke.insertNext(amplifyInstruction);
}
}
}
}
}
}