All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.mirkosertic.bytecoder.classlib.MemoryManager Maven / Gradle / Ivy

There is a newer version: 2024-05-10
Show newest version
/*
 * 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) {
        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