de.mirkosertic.bytecoder.classlib.MemoryManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java.base Show documentation
Show all versions of java.base Show documentation
Bytecoder java.base Module
/*
* Copyright 2017 Mirko Sertic
*
* 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 de.mirkosertic.bytecoder.classlib;
import de.mirkosertic.bytecoder.api.Export;
import de.mirkosertic.bytecoder.api.Import;
/**
* A simple Memory Manager.
*
* It basically holds zwo linked lists. One for the free memory blocks,
* and one for the reserved blocks.
*/
public class MemoryManager {
public static Object[] data;
public static void initTestMemory(int aSize) {
data = new Object[aSize];
}
public static void initWithSize(int aSize) {
initTestMemory(aSize);
initInternal(aSize);
}
@Export("initMemory")
public static void initNative() {
initInternal(Address.getMemorySize());
}
@Import(module = "profiler", name = "logMemoryLayoutBlock")
public static native void logMemoryLayoutBlock(int aStart, int aUsed, int aNext);
private static void initInternal(int aSize) {
// This is the list of free blocks
Address theFreeStart = new Address(4); // At the beginning, we have one giant free block
Address.setIntValue(theFreeStart, 0, 28);
// Free memory block
Address theFree = new Address(28);
Address.setIntValue(theFree, 0, aSize);
Address.setIntValue(theFree, 4, 0);
// This is the List of reserved blocks
Address theReserved = new Address(8);
Address.setIntValue(theReserved, 0, 0);
}
@Export("freeMem")
public static long freeMem() {
long theResult = 0;
Address theFreeStart = new Address(4);
int theFreeStartPtr = Address.getIntValue(theFreeStart, 0);
Address theCurrent = new Address(theFreeStartPtr);
while (Address.getStart(theCurrent) != 0) {
int theSize = Address.getIntValue(theCurrent, 0);
theResult += theSize;
int theNext = Address.getIntValue(theCurrent, 4);
theCurrent = new Address(theNext);
}
return theResult;
}
@Export("usedMem")
public static long usedMem() {
long theResult = 0;
Address theUsedStart = new Address(8);
int theUsedStartPtr = Address.getIntValue(theUsedStart, 0);
Address theCurrent = new Address(theUsedStartPtr);
while (Address.getStart(theCurrent) != 0) {
int theSize = Address.getIntValue(theCurrent, 0);
theResult += theSize;
int theNext = Address.getIntValue(theCurrent, 4);
theCurrent = new Address(theNext);
}
return theResult;
}
@Export("logMemoryLayout")
public static void logMemoryLayout() {
Address theFreeStart = new Address(4);
int theFreeStartPtr = Address.getIntValue(theFreeStart, 0);
Address theCurrent = new Address(theFreeStartPtr);
while (Address.getStart(theCurrent) != 0) {
int theNext = Address.getIntValue(theCurrent, 4);
int theStart = Address.getStart(theCurrent);
logMemoryLayoutBlock(theStart, 0, theNext);
theCurrent = new Address(theNext);
}
Address theUsedStart = new Address(8);
int theUsedStartPtr = Address.getIntValue(theUsedStart, 0);
theCurrent = new Address(theUsedStartPtr);
while (Address.getStart(theCurrent) != 0) {
int theStart = Address.getStart(theCurrent);
int theNext = Address.getIntValue(theCurrent, 4);
logMemoryLayoutBlock(theStart, 1, theNext);
theCurrent = new Address(theNext);
}
}
private static void internalFree(Address aPointer) {
int theStart = Address.getStart(aPointer);
// Remove the block from the list of allocated blocks
Address theAllocatedStart = new Address(8);
int theAllocatedStartPtr = Address.getIntValue(theAllocatedStart, 0);
Address theCurrent = new Address(theAllocatedStartPtr);
int thePrevious = 0;
while(Address.getStart(theCurrent) != 0) {
int theCurrentStart = Address.getStart(theCurrent);
int theNext = Address.getIntValue(theCurrent, 4);
if (theCurrentStart == theStart) {
// This is the block
// Remove it from the list of allocated blocks
if (thePrevious == 0) {
Address.setIntValue(theAllocatedStart, 0, theNext);
} else {
Address thePrevPtr = new Address(thePrevious);
Address.setIntValue(thePrevPtr, 4, theNext);
}
// Ok, now we prepend it to the list of free blocks
Address theFreeStart = new Address(4);
int theFreeStartPtr = Address.getIntValue(theFreeStart, 0);
Address.setIntValue(theCurrent, 4, theFreeStartPtr);
Address.setIntValue(theFreeStart, 0, theCurrentStart);
return;
}
thePrevious = theCurrentStart;
theCurrent = new Address(theNext);
}
}
@Export("free")
public static void free(Address aPointer) {
int theStart = Address.getStart(aPointer);
theStart-=8;
internalFree(new Address(theStart));
}
@Export("malloc")
public static Address malloc(int aSize) {
// Overhead for header
aSize+=8;
Address theFreeStart = new Address(4);
int theFreeStartPtr = Address.getIntValue(theFreeStart, 0);
// We search the free list for a suitable sized block
int thePrevious = 0;
Address theCurrent = new Address(theFreeStartPtr);
while(Address.getStart(theCurrent) != 0) {
int theSize = Address.getIntValue(theCurrent, 0);
int theNext = Address.getIntValue(theCurrent, 4);
if (theSize >= aSize) {
int theRemaining = theSize - aSize;
if (theRemaining > 8) {
Address.setIntValue(theCurrent, 0, aSize);
// Block can be safely split
int theNewFreeStart = Address.getStart(theCurrent) + aSize;
int theNewFreeSize = theSize - aSize;
Address theNewFree = new Address(theNewFreeStart);
Address.setIntValue(theNewFree, 0, theNewFreeSize);
Address.setIntValue(theNewFree, 4, theNext);
if (thePrevious == 0) {
Address.setIntValue(theFreeStart, 0, theNewFreeStart);
} else {
Address thePrev = new Address(thePrevious);
Address.setIntValue(thePrev, 4, theNewFreeStart);
}
} else {
// Remaining size would be too small, be have to completely occupy it
Address.setIntValue(theCurrent, 0, theSize);
if (thePrevious == 0) {
Address.setIntValue(theFreeStart, 0, theNext);
} else {
Address thePrev = new Address(thePrevious);
Address.setIntValue(thePrev, 4, theNext);
}
}
// Add the current block to the allocated block ist by prepending it to the list
Address theReservedListStart = new Address(8);
int theReservedListPtr = Address.getIntValue(theReservedListStart, 0);
int theCurrentStart = Address.getStart(theCurrent);
Address.setIntValue(theCurrent, 4, theReservedListPtr);
Address.setIntValue(theReservedListStart, 0, theCurrentStart);
// Wipeout data
int theDataStart = theCurrentStart + 8;
Address theNewData = new Address(theDataStart);
for (int i=0;i