mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-31 12:24:10 -08:00
WASM: fix metadata intrinsics
This commit is contained in:
parent
9e6061c3f1
commit
f347de44a9
|
@ -20,10 +20,6 @@ import java.util.Arrays;
|
||||||
import org.teavm.classlib.impl.Base46;
|
import org.teavm.classlib.impl.Base46;
|
||||||
import org.teavm.classlib.impl.CharFlow;
|
import org.teavm.classlib.impl.CharFlow;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public final class UnicodeHelper {
|
public final class UnicodeHelper {
|
||||||
private UnicodeHelper() {
|
private UnicodeHelper() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ public final class Example {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
System.out.println(Integer.parseInt("123"));
|
|
||||||
testFibonacci();
|
testFibonacci();
|
||||||
testClasses();
|
testClasses();
|
||||||
testVirtualCall();
|
testVirtualCall();
|
||||||
|
@ -39,7 +38,7 @@ public final class Example {
|
||||||
testArrayIsObject();
|
testArrayIsObject();
|
||||||
testIsAssignableFrom();
|
testIsAssignableFrom();
|
||||||
testExceptions();
|
testExceptions();
|
||||||
//testBigInteger();
|
testBigInteger();
|
||||||
testGC();
|
testGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
if (address == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -406,7 +406,7 @@ public class WasmClassGenerator {
|
||||||
data.cls = cls;
|
data.cls = cls;
|
||||||
|
|
||||||
for (FieldReader field : cls.getFields()) {
|
for (FieldReader field : cls.getFields()) {
|
||||||
int desiredAlignment = getDesiredAlignment(field.getType());
|
int desiredAlignment = getTypeSize(field.getType());
|
||||||
if (field.hasModifier(ElementModifier.STATIC)) {
|
if (field.hasModifier(ElementModifier.STATIC)) {
|
||||||
DataType type = asDataType(field.getType());
|
DataType type = asDataType(field.getType());
|
||||||
data.fieldLayout.put(field.getName(), binaryWriter.append(type.createValue()));
|
data.fieldLayout.put(field.getName(), binaryWriter.append(type.createValue()));
|
||||||
|
@ -450,7 +450,7 @@ public class WasmClassGenerator {
|
||||||
return ((base - 1) / alignment + 1) * alignment;
|
return ((base - 1) / alignment + 1) * alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getDesiredAlignment(ValueType type) {
|
public static int getTypeSize(ValueType type) {
|
||||||
if (type instanceof ValueType.Primitive) {
|
if (type instanceof ValueType.Primitive) {
|
||||||
switch (((ValueType.Primitive) type).getKind()) {
|
switch (((ValueType.Primitive) type).getKind()) {
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
|
|
|
@ -95,7 +95,7 @@ class BuildTimeResourceProxyBuilder {
|
||||||
methods.put(method, (proxy, args) -> descriptor);
|
methods.put(method, (proxy, args) -> descriptor);
|
||||||
break;
|
break;
|
||||||
case "getValues":
|
case "getValues":
|
||||||
methods.put(method, (proxy, args) -> initialData.clone());
|
methods.put(method, (proxy, args) -> proxy.data.clone());
|
||||||
break;
|
break;
|
||||||
case "getPropertyIndex":
|
case "getPropertyIndex":
|
||||||
methods.put(method, (proxy, args) -> propertyIndexes.getOrDefault(args[0], -1));
|
methods.put(method, (proxy, args) -> propertyIndexes.getOrDefault(args[0], -1));
|
||||||
|
|
|
@ -15,10 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.platform.plugin;
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
class BuildTimeResourceSetter implements BuildTimeResourceMethod {
|
class BuildTimeResourceSetter implements BuildTimeResourceMethod {
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.platform.plugin;
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
import org.teavm.ast.InvocationExpr;
|
||||||
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
||||||
import org.teavm.backend.wasm.TeaVMWasmHost;
|
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.TeaVMHost;
|
||||||
import org.teavm.vm.spi.TeaVMPlugin;
|
import org.teavm.vm.spi.TeaVMPlugin;
|
||||||
|
|
||||||
|
@ -28,6 +33,8 @@ public class PlatformPlugin implements TeaVMPlugin {
|
||||||
host.add(new ResourceTransformer());
|
host.add(new ResourceTransformer());
|
||||||
host.add(new ResourceAccessorTransformer(host));
|
host.add(new ResourceAccessorTransformer(host));
|
||||||
host.add(new ResourceAccessorDependencyListener());
|
host.add(new ResourceAccessorDependencyListener());
|
||||||
|
} else {
|
||||||
|
host.add(new StringAmplifierTransformer());
|
||||||
}
|
}
|
||||||
|
|
||||||
TeaVMWasmHost wasmHost = host.getExtension(TeaVMWasmHost.class);
|
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(),
|
wasmHost.add(ctx -> new MetadataIntrinsic(ctx.getClassSource(), ctx.getClassLoader(), ctx.getServices(),
|
||||||
ctx.getProperties()));
|
ctx.getProperties()));
|
||||||
wasmHost.add(ctx -> new ResourceReadIntrinsic(ctx.getClassSource(), ctx.getClassLoader()));
|
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());
|
host.add(new AsyncMethodProcessor());
|
||||||
|
|
|
@ -21,6 +21,8 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.teavm.ast.InvocationExpr;
|
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.WasmIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.WasmIntrinsicManager;
|
import org.teavm.backend.wasm.intrinsics.WasmIntrinsicManager;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
@ -119,8 +121,8 @@ public class ResourceReadIntrinsic implements WasmIntrinsic {
|
||||||
for (Method method : methods) {
|
for (Method method : methods) {
|
||||||
MethodReference methodRef = MethodReference.parse(method);
|
MethodReference methodRef = MethodReference.parse(method);
|
||||||
ValueType propertyType = methodRef.getReturnType();
|
ValueType propertyType = methodRef.getReturnType();
|
||||||
int size = getPropertySize(propertyType);
|
int size = WasmClassGenerator.getTypeSize(propertyType);
|
||||||
currentOffset = ((currentOffset + size - 1) / size + 1) * size;
|
currentOffset = BinaryWriter.align(currentOffset, size);
|
||||||
|
|
||||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor();
|
PropertyDescriptor propertyDescriptor = new PropertyDescriptor();
|
||||||
propertyDescriptor.offset = currentOffset;
|
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 {
|
static class StructureDescriptor {
|
||||||
ResourceTypeDescriptor typeDescriptor;
|
ResourceTypeDescriptor typeDescriptor;
|
||||||
Map<MethodReference, PropertyDescriptor> layout = new HashMap<>();
|
Map<MethodReference, PropertyDescriptor> layout = new HashMap<>();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user