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 {
public static native int log(int amount);
@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 resultSize = 0;
final int heapBase = Address.getHeapBase();
int current = Address.getIntValue(heapBase, 4);
while (current != 0) {
resultSize += Address.getIntValue(current, 0);
current = Address.getIntValue(current, 4);
}
return resultSize;
}
@Export("usedMem")
public static int usedMem() {
int resultSize = 0;
final int heapBase = Address.getHeapBase();
int current = Address.getIntValue(heapBase, 8);
while (current != 0) {
resultSize += Address.getIntValue(current, 0);
current = Address.getIntValue(current, 4);
}
return resultSize;
}
private static void internalFree(final int current) {
final int heapBase = Address.getHeapBase();
final int currentPrev = Address.getIntValue(current, 12);
final int currentNext = Address.getIntValue(current, 4);
if (currentPrev != 0) {
Address.setIntValue(currentPrev, 4, currentNext);
} else {
Address.setIntValue(heapBase, 8, currentNext);
}
if (currentNext != 0) {
Address.setIntValue(currentNext, 12, currentPrev);
}
// Prepend to the list of free blocks
final int freeListHead = Address.getIntValue(heapBase, 4);
Address.setIntValue(current, 4, freeListHead);
Address.setIntValue(freeListHead, 12, current);
Address.setIntValue(current, 12, 0);
Address.setIntValue(heapBase, 4, current);
}
@Export("free")
public static void free(final int aPointer) {
final int pointerToBlock = aPointer - 16;
internalFree(pointerToBlock);
}
@Export("malloc")
public static int malloc(int aSize) {
// Overhead for header
aSize+=16;
final int heapBase = Address.getHeapBase();
int current = Address.getIntValue(heapBase, 4);
while (current != 0) {
final int currentSize = Address.getIntValue(current, 0);
final int currentPrev = Address.getIntValue(current, 12);
final int currentNext = Address.getIntValue(current, 4);
if (currentSize >= aSize) {
final int remaining = currentSize - aSize;
if (remaining < 16) {
// We have an exact match
final int allocatedListHead = Address.getIntValue(heapBase, 8);
final int allocated = current;
Address.setIntValue(allocated, 0, currentSize);
Address.setIntValue(allocated, 4, allocatedListHead);
Address.setIntValue(allocated, 8, 1);
Address.setIntValue(allocated,12, 0);
if (allocatedListHead != 0) {
Address.setIntValue(allocatedListHead, 12, allocated);
}
Address.setIntValue(heapBase, 8, allocated);
if (currentPrev != 0) {
Address.setIntValue(currentPrev, 4, currentNext);
} else {
Address.setIntValue(heapBase, 4, currentNext);
}
if (currentNext != 0) {
Address.setIntValue(currentNext,12, currentPrev);
}
// Wipeout data
final int dataStart = allocated + 16;
final int fillSize = aSize - 16;
if (fillSize == 0) {
/// Nothing to do
} else if (fillSize == 4) {
Address.setIntValue(dataStart, 0, 0);
} else if (fillSize == 8) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
} else if (fillSize == 12) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
Address.setIntValue(dataStart, 8, 0);
} else if (fillSize == 16) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
Address.setIntValue(dataStart, 8, 0);
Address.setIntValue(dataStart, 12, 0);
} else if (fillSize == 20) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
Address.setIntValue(dataStart, 8, 0);
Address.setIntValue(dataStart, 12, 0);
Address.setIntValue(dataStart, 16, 0);
} else if (fillSize == 24) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
Address.setIntValue(dataStart, 8, 0);
Address.setIntValue(dataStart, 12, 0);
Address.setIntValue(dataStart, 16, 0);
Address.setIntValue(dataStart, 20, 0);
} else if (fillSize == 28) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
Address.setIntValue(dataStart, 8, 0);
Address.setIntValue(dataStart, 12, 0);
Address.setIntValue(dataStart, 16, 0);
Address.setIntValue(dataStart, 20, 0);
Address.setIntValue(dataStart, 24, 0);
} else {
for (int i = 0; i < fillSize; i += 4) {
Address.setIntValue(dataStart, i, 0);
}
}
return dataStart;
}
if (remaining > 16) {
// We can use split this chunk
// We create the allocated chunk by appending it to the list of
// allocated blocks
final int allocatedListHead = Address.getIntValue(heapBase, 8);
final int allocated = current;
Address.setIntValue(allocated, 0, aSize);
Address.setIntValue(allocated, 4, allocatedListHead);
Address.setIntValue(allocated, 8, 1);
Address.setIntValue(allocated, 12, 0);
if (allocatedListHead != 0) {
Address.setIntValue(allocatedListHead, 12, allocated);
}
Address.setIntValue(heapBase, 8, allocated);
// Now we split the original block
if (currentPrev != 0) {
final int newFree = current + aSize;
Address.setIntValue(newFree, 0, remaining);
Address.setIntValue(newFree, 4, currentNext);
Address.setIntValue(newFree, 8, 1);
Address.setIntValue(newFree, 12, currentPrev);
if (currentPrev != 0) {
Address.setIntValue(currentPrev, 4, newFree);
}
if (currentNext != 0) {
Address.setIntValue(currentNext, 12, newFree);
}
} else {
final int newFree = current + aSize;
Address.setIntValue(newFree, 0, remaining);
Address.setIntValue(newFree, 4, currentNext);
Address.setIntValue(newFree, 8, 1);
Address.setIntValue(newFree, 12, 0);
if (currentNext != 0) {
Address.setIntValue(currentNext, 12, newFree);
}
Address.setIntValue(heapBase, 4, newFree);
}
// Wipeout data
final int dataStart = allocated + 16;
final int fillSize = aSize - 16;
if (fillSize == 0) {
/// Nothing to do
} else if (fillSize == 4) {
Address.setIntValue(dataStart, 0, 0);
} else if (fillSize == 8) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
} else if (fillSize == 12) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
Address.setIntValue(dataStart, 8, 0);
} else if (fillSize == 16) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
Address.setIntValue(dataStart, 8, 0);
Address.setIntValue(dataStart, 12, 0);
} else if (fillSize == 20) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
Address.setIntValue(dataStart, 8, 0);
Address.setIntValue(dataStart, 12, 0);
Address.setIntValue(dataStart, 16, 0);
} else if (fillSize == 24) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
Address.setIntValue(dataStart, 8, 0);
Address.setIntValue(dataStart, 12, 0);
Address.setIntValue(dataStart, 16, 0);
Address.setIntValue(dataStart, 20, 0);
} else if (fillSize == 28) {
Address.setIntValue(dataStart, 0, 0);
Address.setIntValue(dataStart, 4, 0);
Address.setIntValue(dataStart, 8, 0);
Address.setIntValue(dataStart, 12, 0);
Address.setIntValue(dataStart, 16, 0);
Address.setIntValue(dataStart, 20, 0);
Address.setIntValue(dataStart, 24, 0);
} else {
for (int i = 0; i < fillSize; i += 4) {
Address.setIntValue(dataStart, i, 0);
}
}
return dataStart;
}
}
current = Address.getIntValue(current, 4);
}
Address.unreachable();
return -1;
}
@Export("newObject")
public static int newObject(final int aSize, final int aType, final int aVTableIndex) {
final int allocated = malloc(aSize);
Address.setIntValue(allocated, 0, aType);
Address.setIntValue(allocated, 4, aVTableIndex);
return allocated;
}
public static void initStackObject(final int aPtr, final int aSize, final int aType, final int aVTableIndex) {
// Wipeout data
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, next);
return stepCounter;
}
}
current = next;
}
// 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 newArray = newObject(16 + 4 + 8 * aSize, aType, aVTableIndex);
Address.setIntValue(newArray, 16, aSize);
return newArray;
}
@Export("newArrayINTINTINTINT")
public static int newArray(final int aSize1, final int aSize2, final int aType, final int aVTableIndex) {
final int newArray = newArray(aSize1, aType, aVTableIndex);
for (int i=0;i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy