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;
/**
* A simple Memory Manager.
*
* It basically holds two linked lists. One for the free memory blocks,
* and one for the reserved blocks.
*/
public class MemoryManager {
@Export("initMemory")
public static void initNative() {
initInternal(Address.getMemorySize());
}
private static void initInternal(final int aSize) {
// This is the list of free blocks
final int heapBase = Address.getHeapBase();
final int initialFreeBlock = heapBase + 36;
Address.setIntValue(heapBase, 4, initialFreeBlock);
// Free memory block
Address.setIntValue(initialFreeBlock, 0, aSize - 48 - heapBase);
Address.setIntValue(initialFreeBlock, 4, 0);
Address.setIntValue(initialFreeBlock, 8, 0);
// This is the List of reserved blocks
Address.setIntValue(heapBase, 8, 0);
// Current work counter for GC resumes
Address.setIntValue(heapBase, 12, 0);
// Current counter for GC epochs
Address.setIntValue(heapBase, 16, 1);
}
@Export("GCEpoch")
public static int getGCEpoch() {
final int heapBase = Address.getHeapBase();
return Address.getIntValue(heapBase, 16);
}
@Export("freeMem")
public static int freeMem() {
int theResult = 0;
final int heapBase = Address.getHeapBase();
final int theFreeStartPtr = Address.getIntValue(heapBase, 4);
int theCurrent = theFreeStartPtr;
while (theCurrent != 0) {
theResult += Address.getIntValue(theCurrent, 0);
theCurrent = Address.getIntValue(theCurrent, 4);
}
return theResult;
}
@Export("usedMem")
public static int usedMem() {
int theResult = 0;
final int heapBase = Address.getHeapBase();
int theCurrent = Address.getIntValue(heapBase, 8);
while (theCurrent != 0) {
theResult += Address.getIntValue(theCurrent, 0);
theCurrent = Address.getIntValue(theCurrent, 4);
}
return theResult;
}
private static void internalFree(final int aPointer) {
final int heapBase = Address.getHeapBase();
// Remove the block from the list of allocated blocks
int theCurrent = Address.getIntValue(heapBase, 8);
int thePrevious = 0;
while(theCurrent != 0) {
final int theNext = Address.getIntValue(theCurrent, 4);
if (theCurrent == aPointer) {
// This is the block
// Remove it from the list of allocated blocks
if (thePrevious == 0) {
Address.setIntValue(8, 0, theNext);
} else {
Address.setIntValue(thePrevious, 4, theNext);
}
// Ok, now we prepend it to the list of free blocks
final int theFreeStartPtr = Address.getIntValue(4, 0);
Address.setIntValue(theCurrent, 4, theFreeStartPtr);
Address.setIntValue(4, 0, theCurrent);
return;
}
thePrevious = theCurrent;
theCurrent = theNext;
}
}
@Export("free")
public static void free(final int aPointer) {
int theStart = aPointer;
theStart-=12;
internalFree(theStart);
}
@Export("malloc")
public static int malloc(int aSize) {
// Overhead for header
aSize+=12;
final int heapBase = Address.getHeapBase();
final int theFreeStartPtr = Address.getIntValue(heapBase, 4);
// We search the free list for a suitable sized block
int thePrevious = 0;
int theCurrent = theFreeStartPtr;
while(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 > 12) {
Address.setIntValue(theCurrent, 0, aSize);
// Block can be safely split
final int theNewFreeStart = theCurrent + aSize;
final int theNewFreeSize = theSize - aSize;
Address.setIntValue(theNewFreeStart, 0, theNewFreeSize);
Address.setIntValue(theNewFreeStart, 4, theNext);
if (thePrevious == 0) {
Address.setIntValue(heapBase, 4, theNewFreeStart);
} else {
Address.setIntValue(thePrevious, 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(heapBase, 4, theNext);
} else {
Address.setIntValue(thePrevious, 4, theNext);
}
}
// Add the current block to the allocated block ist by prepending it to the list
final int theReservedListPtr = Address.getIntValue(heapBase, 8);
Address.setIntValue(theCurrent, 4, theReservedListPtr);
Address.setIntValue(heapBase, 8, theCurrent);
// Reset survivor count of the block
Address.setIntValue(theCurrent, 8, 1);
// Wipeout data
final int theDataStart = theCurrent + 12;
for (int i=0;i= blockLimit) {
// We have reached the limit for the current run
// We save the next block to proceed and exit here
Address.setIntValue(heapBase, 12, theNext);
return stepCounter;
}
}
theCurrent = theNext;
}
// Increment epoch
Address.setIntValue(heapBase, 16, currentEpoch + 1);
// The next run starts at the beginning
Address.setIntValue(heapBase, 12, 0);
return freeCounter;
}
@Export("newArrayINTINTINT")
public static int newArray(final int aSize, final int aType, final int aVTableIndex) {
// Arrays are normal objects. Their data are a length field plus n * data
final int theObject = newObject(16 + 4 + 8 * aSize, aType, aVTableIndex);
Address.setIntValue(theObject, 16, aSize);
return theObject;
}
@Export("newArrayINTINTINTINT")
public static int newArray(final int aSize1, final int aSize2, final int aType, final int aVTableIndex) {
final int theResult = newArray(aSize1, aType, aVTableIndex);
for (int i=0;i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy