92 lines
2.6 KiB
Java

package run.jvm.emscripten;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
public class Mem {
public static final int TOTAL_STACK = 5242880;
public static final int TOTAL_MEMORY = 16777216;
private static int alignTo16(int num) {
return ((int) Math.ceil(num / 16.0)) * 16;
}
final ByteBuffer buf;
private int counter = 0;
public Mem(int staticBump) {
this(ByteBuffer.allocateDirect(TOTAL_MEMORY), staticBump);
}
public Mem(ByteBuffer buf, int staticBump) {
this.buf = buf.order(ByteOrder.LITTLE_ENDIAN);
// Emscripten sets where "stack top" can start in mem at position 1024.
// See https://github.com/WebAssembly/binaryen/issues/979
int staticTop = 1024 + staticBump + 16;
int stackBase = alignTo16(staticTop);
int stackTop = stackBase + TOTAL_STACK;
buf.putInt(1024, stackTop);
}
public byte[] getBulk(int index, int len) {
byte[] ret = new byte[len];
if (len > 0) {
ByteBuffer dup = buf.duplicate();
dup.position(index);
dup.get(ret);
}
return ret;
}
public byte[] getCStringBytes(int index) {
if (index == 0) return new byte[0];
// Not really sure the highest performing approach. What we're going to do though is just
// find the first index of 0, then get the array.
int len = 0;
while (buf.get(index + len) != 0) len++;
return getBulk(index, len);
}
public String getCString(int index) {
byte[] bytes = getCStringBytes(index);
if (bytes.length == 0) return "";
return new String(getCStringBytes(index), StandardCharsets.ISO_8859_1);
}
public synchronized int putCString(String str) {
// For now we'll just trust it doesn't already contain a 0
int ret = allocate(str.getBytes(StandardCharsets.ISO_8859_1));
allocate((byte) 0);
return ret;
}
public int putIntArray(int[] arr) {
int ret = counter;
for (int i = 0; i < arr.length; i++) {
buf.putInt(counter, arr[i]);
counter += 4;
}
return ret;
}
public int allocate(byte b) {
int ret = counter;
buf.put(counter, b);
counter++;
return ret;
}
public int allocate(byte[] bytes) {
int ret = counter;
if (bytes.length > 0) {
ByteBuffer dup = buf.duplicate();
dup.position(counter);
dup.put(bytes);
counter += bytes.length;
}
return ret;
}
}