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;
import de.mirkosertic.bytecoder.classlib.java.lang.TString;
/**
* 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(final int aSize) {
data = new Object[aSize];
}
public static void initWithSize(final 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(final int aSize) {
// This is the list of free blocks
final Address theFreeStart = new Address(4); // At the beginning, we have one giant free block
Address.setIntValue(theFreeStart, 0, 28);
// Free memory block
final Address theFree = new Address(28);
Address.setIntValue(theFree, 0, aSize);
Address.setIntValue(theFree, 4, 0);
// This is the List of reserved blocks
final Address theReserved = new Address(8);
Address.setIntValue(theReserved, 0, 0);
}
@Export("freeMem")
public static long freeMem() {
long theResult = 0;
final Address theFreeStart = new Address(4);
final int theFreeStartPtr = Address.getIntValue(theFreeStart, 0);
Address theCurrent = new Address(theFreeStartPtr);
while (Address.getStart(theCurrent) != 0) {
final int theSize = Address.getIntValue(theCurrent, 0);
theResult += theSize;
final int theNext = Address.getIntValue(theCurrent, 4);
theCurrent = new Address(theNext);
}
return theResult;
}
@Export("usedMem")
public static long usedMem() {
long theResult = 0;
final Address theUsedStart = new Address(8);
final int theUsedStartPtr = Address.getIntValue(theUsedStart, 0);
Address theCurrent = new Address(theUsedStartPtr);
while (Address.getStart(theCurrent) != 0) {
final int theSize = Address.getIntValue(theCurrent, 0);
theResult += theSize;
final int theNext = Address.getIntValue(theCurrent, 4);
theCurrent = new Address(theNext);
}
return theResult;
}
@Export("logMemoryLayout")
public static void logMemoryLayout() {
final Address theFreeStart = new Address(4);
final int theFreeStartPtr = Address.getIntValue(theFreeStart, 0);
Address theCurrent = new Address(theFreeStartPtr);
while (Address.getStart(theCurrent) != 0) {
final int theNext = Address.getIntValue(theCurrent, 4);
final int theStart = Address.getStart(theCurrent);
logMemoryLayoutBlock(theStart, 0, theNext);
theCurrent = new Address(theNext);
}
final Address theUsedStart = new Address(8);
final int theUsedStartPtr = Address.getIntValue(theUsedStart, 0);
theCurrent = new Address(theUsedStartPtr);
while (Address.getStart(theCurrent) != 0) {
final int theStart = Address.getStart(theCurrent);
final int theNext = Address.getIntValue(theCurrent, 4);
logMemoryLayoutBlock(theStart, 1, theNext);
theCurrent = new Address(theNext);
}
}
private static void internalFree(final Address aPointer) {
final int theStart = Address.getStart(aPointer);
// Remove the block from the list of allocated blocks
final Address theAllocatedStart = new Address(8);
final int theAllocatedStartPtr = Address.getIntValue(theAllocatedStart, 0);
Address theCurrent = new Address(theAllocatedStartPtr);
int thePrevious = 0;
while(Address.getStart(theCurrent) != 0) {
final int theCurrentStart = Address.getStart(theCurrent);
final 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 {
final Address thePrevPtr = new Address(thePrevious);
Address.setIntValue(thePrevPtr, 4, theNext);
}
// Ok, now we prepend it to the list of free blocks
final Address theFreeStart = new Address(4);
final int theFreeStartPtr = Address.getIntValue(theFreeStart, 0);
Address.setIntValue(theCurrent, 4, theFreeStartPtr);
Address.setIntValue(theFreeStart, 0, theCurrentStart);
return;
}
thePrevious = theCurrentStart;
theCurrent = new Address(theNext);
}
}
public static native void logExceptionText(String aMessage);
public static void logException(final Exception e) throws Exception {
logExceptionText(e.getMessage());
}
@Export("free")
public static void free(final 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;
final Address theFreeStart = new Address(4);
final 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) {
final int theSize = Address.getIntValue(theCurrent, 0);
final int theNext = Address.getIntValue(theCurrent, 4);
if (theSize >= aSize) {
final int theRemaining = theSize - aSize;
if (theRemaining > 8) {
Address.setIntValue(theCurrent, 0, aSize);
// Block can be safely split
final int theNewFreeStart = Address.getStart(theCurrent) + aSize;
final int theNewFreeSize = theSize - aSize;
final Address theNewFree = new Address(theNewFreeStart);
Address.setIntValue(theNewFree, 0, theNewFreeSize);
Address.setIntValue(theNewFree, 4, theNext);
if (thePrevious == 0) {
Address.setIntValue(theFreeStart, 0, theNewFreeStart);
} else {
final 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 {
final 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
final Address theReservedListStart = new Address(8);
final int theReservedListPtr = Address.getIntValue(theReservedListStart, 0);
final int theCurrentStart = Address.getStart(theCurrent);
Address.setIntValue(theCurrent, 4, theReservedListPtr);
Address.setIntValue(theReservedListStart, 0, theCurrentStart);
// Wipeout data
final int theDataStart = theCurrentStart + 8;
final Address theNewData = new Address(theDataStart);
for (int i=0;i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy