package org.trifort.rootbeer.runtime;
import java.util.ArrayList;
import java.util.List;
import org.omg.CORBA._IDLTypeStub;
import org.trifort.rootbeer.generate.bytecode.Constants;
public class FixedMemory implements Memory {
protected long m_address;
protected long m_size;
protected MemPointer m_staticPointer;
protected MemPointer m_instancePointer;
protected MemPointer m_currentPointer;
protected List<List<Long>> m_integerList;
public FixedMemory(long size){
m_address = malloc(size);
if(m_address == 0){
throw new RuntimeException("cannot allocate memory of size: "+size);
}
m_size = size;
m_instancePointer = new MemPointer("instance_mem");
m_staticPointer = new MemPointer("static_mem");
m_currentPointer = m_instancePointer;
m_integerList = new ArrayList<List<Long>>();
}
protected long currPointer(){
return m_currentPointer.m_pointer;
}
@Override
public byte readByte() {
byte ret = doReadByte(currPointer(), m_address);
incrementAddress(1);
return ret;
}
@Override
public boolean readBoolean() {
boolean ret = doReadBoolean(currPointer(), m_address);
incrementAddress(1);
return ret;
}
@Override
public short readShort() {
short ret = doReadShort(currPointer(), m_address);
incrementAddress(2);
return ret;
}
@Override
public int readInt() {
int ret = doReadInt(currPointer(), m_address);
incrementAddress(4);
return ret;
}
@Override
public float readFloat() {
float ret = doReadFloat(currPointer(), m_address);
incrementAddress(4);
return ret;
}
@Override
public double readDouble() {
double ret = doReadDouble(currPointer(), m_address);
incrementAddress(8);
return ret;
}
@Override
public long readLong() {
long ret = doReadLong(currPointer(), m_address);
incrementAddress(8);
return ret;
}
@Override
public long readRef() {
long ret = readInt();
ret = ret << 4;
return ret;
}
@Override
public void writeByte(byte value) {
doWriteByte(currPointer(), value, m_address);
incrementAddress(1);
}
@Override
public void writeBoolean(boolean value) {
doWriteBoolean(currPointer(), value, m_address);
incrementAddress(1);
}
@Override
public void writeShort(short value) {
doWriteShort(currPointer(), value, m_address);
incrementAddress(2);
}
@Override
public void writeInt(int value) {
doWriteInt(currPointer(), value, m_address);
incrementAddress(4);
}
@Override
public void writeRef(long value) {
value = value >> 4;
writeInt((int) value);
}
@Override
public void writeFloat(float value) {
doWriteFloat(currPointer(), value, m_address);
incrementAddress(4);
}
@Override
public void writeDouble(double value) {
doWriteDouble(currPointer(), value, m_address);
incrementAddress(8);
}
@Override
public void writeLong(long value) {
doWriteLong(currPointer(), value, m_address);
incrementAddress(8);
}
@Override
public void readArray(byte[] array){
doReadByteArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void readArray(boolean[] array){
doReadBooleanArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void readArray(short[] array){
doReadShortArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void readArray(int[] array){
doReadIntArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void readArray(float[] array){
doReadFloatArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void readArray(double[] array){
doReadDoubleArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void readArray(long[] array){
doReadLongArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void writeArray(byte[] array){
doWriteByteArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void writeArray(boolean[] array){
doWriteBooleanArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void writeArray(short[] array){
doWriteShortArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void writeArray(int[] array){
doWriteIntArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void writeArray(float[] array){
doWriteFloatArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void writeArray(double[] array){
doWriteDoubleArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public void writeArray(long[] array){
doWriteLongArray(array, m_address+currPointer(), 0, array.length);
}
@Override
public char readChar(){
int value = readInt();
char ret = (char) value;
return ret;
}
@Override
public void writeChar(char value){
writeInt(value);
}
public native void doReadByteArray(byte[] array, long addr, int start, int len);
public native void doReadBooleanArray(boolean[] array, long addr, int start, int len);
public native void doReadShortArray(short[] array, long addr, int start, int len);
public native void doReadIntArray(int[] array, long addr, int start, int len);
public native void doReadFloatArray(float[] array, long addr, int start, int len);
public native void doReadDoubleArray(double[] array, long addr, int start, int len);
public native void doReadLongArray(long[] array, long addr, int start, int len);
public native void doWriteByteArray(byte[] array, long addr, int start, int len);
public native void doWriteBooleanArray(boolean[] array, long addr, int start, int len);
public native void doWriteShortArray(short[] array, long addr, int start, int len);
public native void doWriteIntArray(int[] array, long addr, int start, int len);
public native void doWriteFloatArray(float[] array, long addr, int start, int len);
public native void doWriteDoubleArray(double[] array, long addr, int start, int len);
public native void doWriteLongArray(long[] array, long addr, int start, int len);
public native byte doReadByte(long ptr, long cpu_base);
public native boolean doReadBoolean(long ptr, long cpu_base);
public native short doReadShort(long ptr, long cpu_base);
public native int doReadInt(long ptr, long cpu_base);
public native float doReadFloat(long ptr, long cpu_base);
public native double doReadDouble(long ptr, long cpu_base);
public native long doReadLong(long ptr, long cpu_base);
public native void doWriteByte(long ptr, byte value, long cpu_base);
public native void doWriteBoolean(long ptr, boolean value, long cpu_base);
public native void doWriteShort(long ptr, short value, long cpu_base);
public native void doWriteInt(long ptr, int value, long cpu_base);
public native void doWriteFloat(long ptr, float value, long cpu_base);
public native void doWriteDouble(long ptr, double value, long cpu_base);
public native void doWriteLong(long ptr, long value, long cpu_base);
private native long malloc(long size);
private native void free(long address);
@Override
public void clearHeapEndPtr() {
m_currentPointer.clearHeapEndPtr();
}
@Override
public long getHeapEndPtr() {
return m_currentPointer.m_heapEnd;
}
@Override
public void setHeapEndPtr(long value) {
m_currentPointer.m_heapEnd = value;
}
@Override
public long getSize() {
return m_size;
}
@Override
public long getAddress() {
return m_address;
}
@Override
public long getPointer(){
return m_currentPointer.m_pointer;
}
@Override
public void setAddress(long address) {
m_currentPointer.setAddress(address);
}
@Override
public void incrementAddress(int offset) {
m_currentPointer.incrementAddress(offset);
}
@Override
public long mallocWithSize(int size){
return m_currentPointer.mallocWithSize(size);
}
@Override
public void setPointer(long ptr){
setAddress(ptr);
}
@Override
public void incPointer(long value){
incrementAddress((int) value);
}
@Override
public void pushAddress() {
m_currentPointer.pushAddress();
}
@Override
public void popAddress() {
m_currentPointer.popAddress();
}
@Override
public List<byte[]> getBuffer() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void finishCopy(long size) {
}
@Override
public void finishRead() {
}
@Override
public void readIntArray(int[] array, int size) {
for(int i = 0; i < size; ++i){
array[i] = readInt();
}
}
@Override
public void useInstancePointer() {
m_currentPointer = m_instancePointer;
}
@Override
public void useStaticPointer() {
m_currentPointer = m_staticPointer;
}
@Override
public void align(){
m_currentPointer.align();
}
@Override
public void close() {
free(m_address);
}
public void startIntegerList(){
m_integerList.add(new ArrayList<Long>());
pushAddress();
}
public void addIntegerToList(long value){
List<Long> top = m_integerList.get(m_integerList.size()-1);
top.add(value);
}
public void endIntegerList(){
popAddress();
List<Long> top = m_integerList.get(m_integerList.size()-1);
for(Long curr : top){
writeRef(curr);
}
m_integerList.remove(m_integerList.size()-1);
}
public void finishReading(){
long ptr = m_currentPointer.m_pointer;
int mod = (int) (ptr % Constants.MallocAlignBytes);
if(mod != 0){
ptr += (Constants.MallocAlignBytes - mod);
}
setPointer(ptr);
}
@Override
public void align16(){
m_instancePointer.align16();
m_staticPointer.align16();
}
private class MemPointer {
private PointerStack m_stack;
private long m_pointer;
private long m_heapEnd;
private String name;
public MemPointer(String name){
this.name = name;
m_stack = new PointerStack();
}
public String getName() {
return name;
}
public void popAddress() {
m_pointer = m_stack.pop();
}
public void pushAddress() {
m_stack.push(m_pointer);
}
public long mallocWithSize(int size){
int mod = size % Constants.MallocAlignBytes;
if(mod != 0){
size += (Constants.MallocAlignBytes - mod);
}
long mod2 = m_heapEnd % Constants.MallocAlignBytes;
if(mod2 != 0){
m_heapEnd += (Constants.MallocAlignBytes - mod2);
}
long ret = m_heapEnd;
m_heapEnd += size;
if(ret + size > m_size){
throw new OutOfMemoryError("currentHeapEnd: "+ret+" allocationSize: "+size+" memorySize: "+m_size);
}
m_pointer = ret;
return ret;
}
private void clearHeapEndPtr() {
m_heapEnd = 0;
m_pointer = 0;
}
private void setAddress(long address) {
m_pointer = address;
if(address > m_heapEnd)
m_heapEnd = address;
}
private void incrementAddress(int offset) {
m_pointer += offset;
if(m_pointer > m_heapEnd){
m_heapEnd = m_pointer;
}
}
private void align() {
long mod = m_pointer % 8;
if(mod != 0){
m_pointer += (8 - mod);
}
if(m_pointer > m_heapEnd){
m_heapEnd = m_pointer;
}
}
public void align16() {
long mod = m_heapEnd % Constants.MallocAlignBytes;
if(mod != 0){
m_heapEnd += (Constants.MallocAlignBytes - mod);
}
}
}
}