mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Implementing System.arraycopy
This commit is contained in:
parent
cc9af93021
commit
ca3258417b
|
@ -21,11 +21,13 @@ import org.teavm.classlib.java.io.TPrintStream;
|
||||||
import org.teavm.classlib.java.lang.reflect.TArray;
|
import org.teavm.classlib.java.lang.reflect.TArray;
|
||||||
import org.teavm.dependency.PluggableDependency;
|
import org.teavm.dependency.PluggableDependency;
|
||||||
import org.teavm.backend.javascript.spi.GeneratedBy;
|
import org.teavm.backend.javascript.spi.GeneratedBy;
|
||||||
|
import org.teavm.interop.Address;
|
||||||
|
import org.teavm.interop.DelegateTo;
|
||||||
|
import org.teavm.interop.Structure;
|
||||||
|
import org.teavm.runtime.Allocator;
|
||||||
|
import org.teavm.runtime.RuntimeArray;
|
||||||
|
import org.teavm.runtime.RuntimeClass;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public final class TSystem extends TObject {
|
public final class TSystem extends TObject {
|
||||||
public static final TPrintStream out = new TPrintStream(new TConsoleOutputStreamStdout(), false);
|
public static final TPrintStream out = new TPrintStream(new TConsoleOutputStreamStdout(), false);
|
||||||
public static final TPrintStream err = new TPrintStream(new TConsoleOutputStreamStderr(), false);
|
public static final TPrintStream err = new TPrintStream(new TConsoleOutputStreamStderr(), false);
|
||||||
|
@ -74,8 +76,25 @@ public final class TSystem extends TObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GeneratedBy(SystemNativeGenerator.class)
|
@GeneratedBy(SystemNativeGenerator.class)
|
||||||
|
@DelegateTo("doArrayCopyLowLevel")
|
||||||
private static native void doArrayCopy(Object src, int srcPos, Object dest, int destPos, int length);
|
private static native void doArrayCopy(Object src, int srcPos, Object dest, int destPos, int length);
|
||||||
|
|
||||||
|
static void doArrayCopyLowLevel(RuntimeArray src, int srcPos, RuntimeArray dest, int destPos, int length) {
|
||||||
|
RuntimeClass type = Address.fromInt(src.classReference << 3).toStructure();
|
||||||
|
int itemSize = type.itemType.size;
|
||||||
|
if ((type.itemType.flags & RuntimeClass.PRIMITIVE) == 0) {
|
||||||
|
itemSize = Address.sizeOf();
|
||||||
|
}
|
||||||
|
|
||||||
|
Address srcAddress = Address.align(src.toAddress().add(RuntimeArray.class, 1), itemSize);
|
||||||
|
srcAddress = srcAddress.add(itemSize * srcPos);
|
||||||
|
|
||||||
|
Address destAddress = Address.align(dest.toAddress().add(RuntimeArray.class, 1), itemSize);
|
||||||
|
destAddress = destAddress.add(itemSize * destPos);
|
||||||
|
|
||||||
|
Allocator.moveMemoryBlock(srcAddress, destAddress, length * itemSize);
|
||||||
|
}
|
||||||
|
|
||||||
@GeneratedBy(SystemNativeGenerator.class)
|
@GeneratedBy(SystemNativeGenerator.class)
|
||||||
public static native long currentTimeMillis();
|
public static native long currentTimeMillis();
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ public final class Example {
|
||||||
testLazyInitialization();
|
testLazyInitialization();
|
||||||
testHashCode();
|
testHashCode();
|
||||||
testArrayList();
|
testArrayList();
|
||||||
|
//testArrayCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testFibonacci() {
|
private static void testFibonacci() {
|
||||||
|
@ -101,6 +102,25 @@ public final class Example {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void testArrayCopy() {
|
||||||
|
byte[] array = new byte[100];
|
||||||
|
byte[] negatives = new byte[100];
|
||||||
|
for (int i = 0; i < array.length; ++i) {
|
||||||
|
array[i] = (byte) i;
|
||||||
|
negatives[i] = (byte) -i;
|
||||||
|
}
|
||||||
|
System.arraycopy(negatives, 4, array, 0, 12);
|
||||||
|
System.arraycopy(negatives, 1, array, 21, 12);
|
||||||
|
System.arraycopy(negatives, 2, array, 35, 12);
|
||||||
|
System.arraycopy(negatives, 1, array, 8, 3);
|
||||||
|
System.arraycopy(array, 50, array, 54, 12);
|
||||||
|
StringBuilder sb = new StringBuilder("arrayCopy result:");
|
||||||
|
for (int i = 0; i < array.length; ++i) {
|
||||||
|
sb.append(" ").append(array[i]);
|
||||||
|
}
|
||||||
|
println(sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
private static Base instance(int index) {
|
private static Base instance(int index) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
|
@ -166,7 +166,7 @@ public final class WasmRuntime {
|
||||||
return (a << 56) | (b << 48) | (c << 40) | (d << 32) | (e << 24) | (f << 16) | (g << 8) | h;
|
return (a << 56) | (b << 48) | (c << 40) | (d << 32) | (e << 24) | (f << 16) | (g << 8) | h;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Address align(Address address, int alignment) {
|
public static Address align(Address address, int alignment) {
|
||||||
int value = address.toInt();
|
int value = address.toInt();
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
return address;
|
return address;
|
||||||
|
@ -232,8 +232,125 @@ public final class WasmRuntime {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (address = Address.fromInt(alignedStart + 1); address.toInt() < alignedEnd; address = address.add(4)) {
|
for (address = Address.fromInt(alignedStart + 4); address.toInt() < alignedEnd; address = address.add(4)) {
|
||||||
address.putInt(0);
|
address.putInt(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void moveMemoryBlock(Address source, Address target, int count) {
|
||||||
|
if (count < 8) {
|
||||||
|
slowMemoryMove(source, target, count);
|
||||||
|
}
|
||||||
|
int diff = source.toInt() - target.toInt();
|
||||||
|
if (diff == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((diff & 3) != 0) {
|
||||||
|
slowMemoryMove(source, target, count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Address alignedSourceStart = Address.fromInt(source.toInt() >>> 2 << 2);
|
||||||
|
Address alignedTargetStart = Address.fromInt(target.toInt() >>> 2 << 2);
|
||||||
|
|
||||||
|
Address alignedSourceEnd = Address.fromInt((source.toInt() + count) >>> 2 << 2);
|
||||||
|
Address alignedTargetEnd = Address.fromInt((target.toInt() + count) >>> 2 << 2);
|
||||||
|
|
||||||
|
if (source.toInt() > target.toInt()) {
|
||||||
|
switch (source.toInt() - alignedSourceStart.toInt()) {
|
||||||
|
case 0:
|
||||||
|
alignedTargetStart.putInt(alignedSourceStart.getInt());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
alignedTargetStart.add(3).putByte(alignedSourceStart.add(3).getByte());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
alignedTargetStart.add(2).putShort(alignedSourceStart.add(2).getShort());
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
alignedTargetStart.add(1).putByte(alignedSourceStart.add(1).getByte());
|
||||||
|
alignedTargetStart.add(2).putShort(alignedSourceStart.add(2).getShort());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
alignedSourceStart = alignedSourceStart.add(4);
|
||||||
|
alignedTargetStart = alignedTargetStart.add(4);
|
||||||
|
|
||||||
|
while (alignedSourceStart.toInt() < alignedSourceEnd.toInt()) {
|
||||||
|
alignedTargetStart.putInt(alignedSourceStart.getInt());
|
||||||
|
alignedSourceStart = alignedSourceStart.add(4);
|
||||||
|
alignedTargetStart = alignedTargetStart.add(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (source.getInt() + count - alignedSourceEnd.getInt()) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
alignedTargetEnd.putByte(alignedSourceEnd.getByte());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
alignedTargetEnd.putShort(alignedSourceEnd.getShort());
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
alignedTargetEnd.putShort(alignedSourceEnd.getShort());
|
||||||
|
alignedTargetEnd.add(2).putByte(alignedSourceEnd.add(2).getByte());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (source.getInt() + count - alignedSourceEnd.getInt()) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
alignedTargetEnd.putByte(alignedSourceEnd.getByte());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
alignedTargetEnd.putShort(alignedSourceEnd.getShort());
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
alignedTargetEnd.add(2).putByte(alignedSourceEnd.add(2).getByte());
|
||||||
|
alignedTargetEnd.putShort(alignedSourceEnd.getShort());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (alignedSourceEnd.toInt() > alignedTargetEnd.toInt()) {
|
||||||
|
alignedTargetEnd.putInt(alignedSourceEnd.getInt());
|
||||||
|
alignedSourceEnd = alignedSourceEnd.add(-4);
|
||||||
|
alignedTargetEnd = alignedTargetEnd.add(-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (source.toInt() - alignedSourceStart.toInt()) {
|
||||||
|
case 0:
|
||||||
|
alignedTargetStart.putInt(alignedSourceStart.getInt());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
alignedTargetStart.add(3).putByte(alignedSourceStart.add(3).getByte());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
alignedTargetStart.add(2).putShort(alignedSourceStart.add(2).getShort());
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
alignedTargetStart.add(2).putShort(alignedSourceStart.add(2).getShort());
|
||||||
|
alignedTargetStart.add(1).putByte(alignedSourceStart.add(1).getByte());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void slowMemoryMove(Address source, Address target, int count) {
|
||||||
|
if (source.toInt() > target.toInt()) {
|
||||||
|
while (count-- > 0) {
|
||||||
|
target.putByte(source.getByte());
|
||||||
|
target = target.add(1);
|
||||||
|
source = source.add(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
source.add(count);
|
||||||
|
target.add(count);
|
||||||
|
while (count-- > 0) {
|
||||||
|
target = target.add(-1);
|
||||||
|
source = source.add(-1);
|
||||||
|
target.putByte(source.getByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,13 @@ import org.teavm.backend.wasm.generate.WasmGenerationContext;
|
||||||
import org.teavm.backend.wasm.generate.WasmGenerator;
|
import org.teavm.backend.wasm.generate.WasmGenerator;
|
||||||
import org.teavm.backend.wasm.generate.WasmMangling;
|
import org.teavm.backend.wasm.generate.WasmMangling;
|
||||||
import org.teavm.backend.wasm.generate.WasmStringPool;
|
import org.teavm.backend.wasm.generate.WasmStringPool;
|
||||||
|
import org.teavm.backend.wasm.intrinsics.AddressIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.AllocatorIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.AllocatorIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.ClassIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.ClassIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.PlatformClassIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.PlatformClassIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.PlatformClassMetadataIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.PlatformClassMetadataIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.PlatformIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.PlatformIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.PlatformObjectIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.PlatformObjectIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.WasmAddressIntrinsic;
|
|
||||||
import org.teavm.backend.wasm.intrinsics.WasmRuntimeIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.WasmRuntimeIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.WasmStructureIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.WasmStructureIntrinsic;
|
||||||
import org.teavm.backend.wasm.model.WasmFunction;
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
|
@ -196,7 +196,7 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
WasmGenerationContext context = new WasmGenerationContext(classes, controller.getDiagnostics(),
|
WasmGenerationContext context = new WasmGenerationContext(classes, controller.getDiagnostics(),
|
||||||
vtableProvider, tagRegistry, stringPool);
|
vtableProvider, tagRegistry, stringPool);
|
||||||
|
|
||||||
context.addIntrinsic(new WasmAddressIntrinsic());
|
context.addIntrinsic(new AddressIntrinsic(classGenerator));
|
||||||
context.addIntrinsic(new WasmStructureIntrinsic(classGenerator));
|
context.addIntrinsic(new WasmStructureIntrinsic(classGenerator));
|
||||||
context.addIntrinsic(new WasmRuntimeIntrinsic());
|
context.addIntrinsic(new WasmRuntimeIntrinsic());
|
||||||
context.addIntrinsic(new AllocatorIntrinsic());
|
context.addIntrinsic(new AllocatorIntrinsic());
|
||||||
|
@ -293,7 +293,7 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
if (clinit == null) {
|
if (clinit == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
initFunction.getBody().add(new WasmCall(WasmMangling.mangleMethod(clinit.getReference())));
|
initFunction.getBody().add(new WasmCall(WasmMangling.mangleInitializer(className)));
|
||||||
}
|
}
|
||||||
module.add(initFunction);
|
module.add(initFunction);
|
||||||
module.setStartFunction(initFunction);
|
module.setStartFunction(initFunction);
|
||||||
|
|
|
@ -202,6 +202,13 @@ public class WasmClassGenerator {
|
||||||
return data.size;
|
return data.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getClassAlignment(String className) {
|
||||||
|
ValueType type = ValueType.object(className);
|
||||||
|
addClass(type);
|
||||||
|
ClassBinaryData data = binaryDataMap.get(type);
|
||||||
|
return data.alignment;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isStructure(String className) {
|
public boolean isStructure(String className) {
|
||||||
ValueType type = ValueType.object(className);
|
ValueType type = ValueType.object(className);
|
||||||
addClass(type);
|
addClass(type);
|
||||||
|
@ -217,11 +224,13 @@ public class WasmClassGenerator {
|
||||||
addClass(ValueType.object(cls.getParent()));
|
addClass(ValueType.object(cls.getParent()));
|
||||||
ClassBinaryData parentData = binaryDataMap.get(ValueType.object(cls.getParent()));
|
ClassBinaryData parentData = binaryDataMap.get(ValueType.object(cls.getParent()));
|
||||||
data.size = parentData.size;
|
data.size = parentData.size;
|
||||||
|
data.alignment = parentData.alignment;
|
||||||
if (parentData.start == -1) {
|
if (parentData.start == -1) {
|
||||||
data.start = -1;
|
data.start = -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data.size = 4;
|
data.size = 4;
|
||||||
|
data.alignment = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FieldReader field : cls.getFields()) {
|
for (FieldReader field : cls.getFields()) {
|
||||||
|
@ -234,6 +243,9 @@ public class WasmClassGenerator {
|
||||||
data.fieldLayout.put(field.getName(), offset);
|
data.fieldLayout.put(field.getName(), offset);
|
||||||
data.size = offset + desiredAlignment;
|
data.size = offset + desiredAlignment;
|
||||||
}
|
}
|
||||||
|
if (data.alignment == 0) {
|
||||||
|
data.alignment = desiredAlignment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +271,7 @@ public class WasmClassGenerator {
|
||||||
return DataPrimitives.ADDRESS;
|
return DataPrimitives.ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int align(int base, int alignment) {
|
public static int align(int base, int alignment) {
|
||||||
if (base == 0) {
|
if (base == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -312,6 +324,7 @@ public class WasmClassGenerator {
|
||||||
private class ClassBinaryData {
|
private class ClassBinaryData {
|
||||||
ValueType type;
|
ValueType type;
|
||||||
int size;
|
int size;
|
||||||
|
int alignment;
|
||||||
int start;
|
int start;
|
||||||
ObjectIntMap<String> fieldLayout = new ObjectIntOpenHashMap<>();
|
ObjectIntMap<String> fieldLayout = new ObjectIntOpenHashMap<>();
|
||||||
DataValue data;
|
DataValue data;
|
||||||
|
|
|
@ -83,9 +83,8 @@ public class WasmGenerator {
|
||||||
new WasmInt32Constant(RuntimeClass.INITIALIZED));
|
new WasmInt32Constant(RuntimeClass.INITIALIZED));
|
||||||
|
|
||||||
WasmConditional conditional = new WasmConditional(initFlag);
|
WasmConditional conditional = new WasmConditional(initFlag);
|
||||||
MethodReference clinit = new MethodReference(method.getOwnerName(),
|
conditional.getThenBlock().getBody().add(new WasmCall(
|
||||||
"<clinit>", ValueType.VOID);
|
WasmMangling.mangleInitializer(method.getOwnerName())));
|
||||||
conditional.getThenBlock().getBody().add(new WasmCall(WasmMangling.mangleMethod(clinit)));
|
|
||||||
function.getBody().add(conditional);
|
function.getBody().add(conditional);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.intrinsics;
|
package org.teavm.backend.wasm.intrinsics;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.teavm.ast.ConstantExpr;
|
||||||
import org.teavm.ast.InvocationExpr;
|
import org.teavm.ast.InvocationExpr;
|
||||||
|
import org.teavm.backend.wasm.WasmRuntime;
|
||||||
|
import org.teavm.backend.wasm.generate.WasmClassGenerator;
|
||||||
|
import org.teavm.backend.wasm.generate.WasmMangling;
|
||||||
import org.teavm.backend.wasm.model.WasmType;
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt32Subtype;
|
import org.teavm.backend.wasm.model.expression.WasmInt32Subtype;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt64Subtype;
|
import org.teavm.backend.wasm.model.expression.WasmInt64Subtype;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
|
@ -36,7 +43,13 @@ import org.teavm.interop.Address;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
public class WasmAddressIntrinsic implements WasmIntrinsic {
|
public class AddressIntrinsic implements WasmIntrinsic {
|
||||||
|
private WasmClassGenerator classGenerator;
|
||||||
|
|
||||||
|
public AddressIntrinsic(WasmClassGenerator classGenerator) {
|
||||||
|
this.classGenerator = classGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isApplicable(MethodReference methodReference) {
|
public boolean isApplicable(MethodReference methodReference) {
|
||||||
return methodReference.getClassName().equals(Address.class.getName());
|
return methodReference.getClassName().equals(Address.class.getName());
|
||||||
|
@ -61,11 +74,24 @@ public class WasmAddressIntrinsic implements WasmIntrinsic {
|
||||||
}
|
}
|
||||||
case "add": {
|
case "add": {
|
||||||
WasmExpression base = manager.generate(invocation.getArguments().get(0));
|
WasmExpression base = manager.generate(invocation.getArguments().get(0));
|
||||||
WasmExpression offset = manager.generate(invocation.getArguments().get(1));
|
if (invocation.getMethod().parameterCount() == 1) {
|
||||||
if (invocation.getMethod().parameterType(0) == ValueType.LONG) {
|
WasmExpression offset = manager.generate(invocation.getArguments().get(1));
|
||||||
offset = new WasmConversion(WasmType.INT64, WasmType.INT32, false, offset);
|
if (invocation.getMethod().parameterType(0) == ValueType.LONG) {
|
||||||
|
offset = new WasmConversion(WasmType.INT64, WasmType.INT32, false, offset);
|
||||||
|
}
|
||||||
|
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, base, offset);
|
||||||
|
} else {
|
||||||
|
WasmExpression offset = manager.generate(invocation.getArguments().get(2));
|
||||||
|
Object type = ((ConstantExpr) invocation.getArguments().get(1)).getValue();
|
||||||
|
String className = ((ValueType.Object) type).getClassName();
|
||||||
|
int size = classGenerator.getClassSize(className);
|
||||||
|
int alignment = classGenerator.getClassAlignment(className);
|
||||||
|
size = WasmClassGenerator.align(size, alignment);
|
||||||
|
|
||||||
|
offset = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.MUL, offset,
|
||||||
|
new WasmInt32Constant(size));
|
||||||
|
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, base, offset);
|
||||||
}
|
}
|
||||||
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, base, offset);
|
|
||||||
}
|
}
|
||||||
case "getByte":
|
case "getByte":
|
||||||
return new WasmLoadInt32(1, manager.generate(invocation.getArguments().get(0)),
|
return new WasmLoadInt32(1, manager.generate(invocation.getArguments().get(0)),
|
||||||
|
@ -121,6 +147,17 @@ public class WasmAddressIntrinsic implements WasmIntrinsic {
|
||||||
WasmExpression value = manager.generate(invocation.getArguments().get(1));
|
WasmExpression value = manager.generate(invocation.getArguments().get(1));
|
||||||
return new WasmStoreFloat64(8, address, value);
|
return new WasmStoreFloat64(8, address, value);
|
||||||
}
|
}
|
||||||
|
case "sizeOf":
|
||||||
|
return new WasmInt32Constant(4);
|
||||||
|
case "align": {
|
||||||
|
MethodReference delegate = new MethodReference(WasmRuntime.class.getName(),
|
||||||
|
invocation.getMethod().getDescriptor());
|
||||||
|
WasmCall call = new WasmCall(WasmMangling.mangleMethod(delegate));
|
||||||
|
call.getArguments().addAll(invocation.getArguments().stream()
|
||||||
|
.map(arg -> manager.generate(arg))
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
return call;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||||
}
|
}
|
|
@ -21,7 +21,6 @@ import org.teavm.backend.wasm.WasmRuntime;
|
||||||
import org.teavm.backend.wasm.generate.WasmMangling;
|
import org.teavm.backend.wasm.generate.WasmMangling;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
import org.teavm.interop.Address;
|
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.runtime.Allocator;
|
import org.teavm.runtime.Allocator;
|
||||||
|
|
||||||
|
@ -35,9 +34,11 @@ public class AllocatorIntrinsic implements WasmIntrinsic {
|
||||||
@Override
|
@Override
|
||||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||||
switch (invocation.getMethod().getName()) {
|
switch (invocation.getMethod().getName()) {
|
||||||
case "fillZero": {
|
case "fillZero":
|
||||||
WasmCall call = new WasmCall(WasmMangling.mangleMethod(new MethodReference(WasmRuntime.class,
|
case "moveMemoryBlock": {
|
||||||
"fillZero", Address.class, int.class, void.class)));
|
MethodReference delegateMetod = new MethodReference(WasmRuntime.class.getName(),
|
||||||
|
invocation.getMethod().getDescriptor());
|
||||||
|
WasmCall call = new WasmCall(WasmMangling.mangleMethod(delegateMetod));
|
||||||
call.getArguments().addAll(invocation.getArguments().stream().map(manager::generate)
|
call.getArguments().addAll(invocation.getArguments().stream().map(manager::generate)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
return call;
|
return call;
|
||||||
|
|
|
@ -51,4 +51,6 @@ public final class Allocator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static native void fillZero(Address address, int count);
|
public static native void fillZero(Address address, int count);
|
||||||
|
|
||||||
|
public static native void moveMemoryBlock(Address source, Address target, int count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,4 +59,10 @@ public final class Address {
|
||||||
public static native Address fromLong(long value);
|
public static native Address fromLong(long value);
|
||||||
|
|
||||||
public static native Address ofObject(Object obj);
|
public static native Address ofObject(Object obj);
|
||||||
|
|
||||||
|
public static native Address align(Address address, int alignment);
|
||||||
|
|
||||||
|
public static native int sizeOf();
|
||||||
|
|
||||||
|
public native Address add(Class<? extends Structure> type, int offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,4 @@ public class Structure {
|
||||||
public final native Address toAddress();
|
public final native Address toAddress();
|
||||||
|
|
||||||
public static native int sizeOf(Class<? extends Structure> type);
|
public static native int sizeOf(Class<? extends Structure> type);
|
||||||
|
|
||||||
public static native <T extends Structure> T add(T base, int offset);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,6 @@ import org.teavm.platform.metadata.ClassResource;
|
||||||
import org.teavm.platform.metadata.StaticFieldResource;
|
import org.teavm.platform.metadata.StaticFieldResource;
|
||||||
import org.teavm.platform.plugin.PlatformGenerator;
|
import org.teavm.platform.plugin.PlatformGenerator;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public final class Platform {
|
public final class Platform {
|
||||||
private Platform() {
|
private Platform() {
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user