Package org.jnode.vm.memmgr.mmtk

Source Code of org.jnode.vm.memmgr.mmtk.BaseMmtkHeapManager

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.vm.memmgr.mmtk;

import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import javax.naming.NameNotFoundException;

import org.jnode.bootlog.BootLogInstance;
import org.jnode.naming.InitialNaming;
import org.jnode.system.resource.MemoryResource;
import org.jnode.system.resource.ResourceManager;
import org.jnode.system.resource.ResourceNotFreeException;
import org.jnode.system.resource.ResourceOwner;
import org.jnode.vm.Unsafe;
import org.jnode.vm.classmgr.ObjectLayout;
import org.jnode.vm.classmgr.VmArrayClass;
import org.jnode.vm.classmgr.VmClassLoader;
import org.jnode.vm.classmgr.VmClassType;
import org.jnode.vm.classmgr.VmNormalClass;
import org.jnode.vm.classmgr.VmType;
import org.jnode.vm.facade.HeapStatistics;
import org.jnode.vm.facade.ObjectFilter;
import org.jnode.vm.facade.VmArchitecture;
import org.jnode.vm.facade.VmProcessor;
import org.jnode.vm.facade.VmUtils;
import org.jnode.vm.memmgr.HeapHelper;
import org.jnode.vm.memmgr.VmHeapManager;
import org.mmtk.plan.BasePlan;
import org.mmtk.policy.Space;
import org.mmtk.utility.heap.HeapGrowthManager;
import org.mmtk.utility.heap.LazyMmapper;
import org.mmtk.utility.scan.MMType;
import org.mmtk.vm.Memory;
import org.mmtk.vm.SynchronizedCounter;
import org.vmmagic.pragma.Uninterruptible;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.Extent;
import org.vmmagic.unboxed.ObjectReference;
import org.vmmagic.unboxed.Offset;
import org.vmmagic.unboxed.Word;

/**
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public abstract class BaseMmtkHeapManager extends VmHeapManager implements
        Uninterruptible {

    /** <code>true</code> if built with GCSpy */
    private static final boolean WITH_GCSPY = false;

    /** Used by mmtypes for arrays */
    private final int[] EMPY_INT_ARRAY = new int[0];

    /** Offset in bytes of the flags from the object reference */
    private final int flagsOffset;

    /** Offset in bytes of the TIB reference from the object reference */
    private final int tibOffset;

    /** Size of the java header in bytes */
    private final int headerSize;

    /** Resource used to claim the memory region occupied by the available heap */
    private MemoryResource heapResource;

    /**
     * Is this heapmanager busy initializing (used to detect recursion in
     * initialize)
     */
    private boolean initializing;

    /**
     * @param loader
     * @param helper
     */
    public BaseMmtkHeapManager(VmClassLoader loader, HeapHelper helper) {
        super(helper);
        final int refSize = loader.getArchitecture().getReferenceSize();
        this.flagsOffset = ObjectLayout.FLAGS_SLOT * refSize;
        this.tibOffset = ObjectLayout.TIB_SLOT * refSize;
        this.headerSize = ObjectLayout.HEADER_SLOTS * refSize;
        setWriteBarrier(null);
    }

    public final Object createProcessorHeapData(VmProcessor cpu) {
        try {
            final Class[] types = { HeapHelper.class };
            final Class cls = Class.forName("org.mmtk.vm.Plan");
            final Constructor cons = cls.getConstructor(types);
            return cons.newInstance(new Object[] { helper });
        } catch (ClassNotFoundException ex) {
            throw new InternalError("Plan class not found");
        } catch (NoSuchMethodException ex) {
            ex.printStackTrace();
            throw new InternalError("Plan(HeapHelper) constructor not found");
        } catch (InstantiationException ex) {
            throw new InternalError("Cannot instantiate Plan");
        } catch (IllegalAccessException ex) {
            throw new InternalError("Cannot access Plan");
        } catch (InvocationTargetException ex) {
            throw (InternalError) new InternalError("Error instantiating Plan")
                    .initCause(ex.getTargetException());
        }
    }

    protected Object allocObject(VmClassType< ? > vmClass, int size) {
        if (false) {
            Unsafe.debug("allocObject: ");
            Unsafe.debug(vmClass.getName());
            Unsafe.debug('\n');
        }
        if (false) {
          getCurrentProcessor().getArchitecture().getStackReader()
                    .debugStackTrace();
        }

        final int align = ObjectLayout.OBJECT_ALIGN;
        final Word headerSize = Word.fromIntZeroExtend(this.headerSize);
        final Offset tibOffset = Offset.fromIntSignExtend(this.tibOffset);
        final Offset flagsOffset = Offset.fromIntSignExtend(this.flagsOffset);
        int allocator = BasePlan.ALLOC_DEFAULT;

        final int refSize = VmUtils.getVm().getArch().getReferenceSize();
        allocator = checkAllocator(size, align, allocator);

        // Allocate the raw space
        size += this.headerSize;
        final Address ptr = alloc(size, align, this.headerSize, allocator);

        // Initialize the header
        final Address objPtr = ptr.add(headerSize);
        final ObjectReference tibRef = ObjectReference.fromObject(vmClass
                .getTIB());
        objPtr.store(tibRef, tibOffset);
        objPtr.store((int) 0, flagsOffset);

        // Post allocation
        final Object result = objPtr.toObjectReference().toObject();
        if (false) {
            Unsafe.debug("result=");
            Unsafe.debug(objPtr);
            Unsafe.debug('\n');
        }
        postAlloc(ObjectReference.fromObject(result), ObjectReference
                .fromObject(vmClass), size, allocator);

        return result;
    }

    public void dumpStatistics(PrintWriter out) {
        // Default behavior is to do nothing
    }

    public void gc() {
        // Default behavior is to do nothing
    }

    public long getFreeMemory() {
        return BasePlan.freeMemory().toLong();
    }

    /**
     * {@inheritDoc}
     */
    public HeapStatistics getHeapStatistics(ObjectFilter objectFilter) {
        return null;
    }

    public long getTotalMemory() {
        return BasePlan.totalMemory().toLong();
    }

    protected void initialize() {
        Unsafe.debug("MmtkHeapManager#initialize\n");
        if (initializing) {
          getCurrentProcessor().getArchitecture().getStackReader()
                    .debugStackTrace();
            Unsafe.die("Recursive initialize");
        }
        initializing = true;
        final VmArchitecture arch = VmUtils.getVm().getArch();
        helper.bootArchitecture(true);

        final Address bootImgStart = helper.getBootImageStart();
        final Address bootImgEnd = helper.getBootImageEnd();
        final int bootImgSize = bootImgEnd.sub(bootImgStart.toWord()).toInt();
        LazyMmapper.boot(bootImgStart, bootImgSize);

        final Extent heapSize = helper.getHeapSize();
        HeapGrowthManager.boot(heapSize, heapSize);
        bootPlan();
        SynchronizedCounter.boot();
        initializing = false;
        Unsafe.debug("MmtkHeapManager#initialize done\n");

        Space.printVMMap();
    }

    public boolean isLowOnMemory() {
        // TODO Auto-generated method stub
        return false;
    }

    public boolean isObject(Address ptr) {
        return Space.isMappedAddress(ptr);
    }

    public void start() {
        Unsafe.debug("MmtkHeapManager#start\n");

        // Claim the available heap region as resource.
        try {
            final ResourceManager rm = InitialNaming.lookup(ResourceManager.NAME);
            final Address start = Memory.AVAILABLE_START();
            final Extent size = Memory.AVAILABLE_END().toWord().sub(start.toWord()).toExtent();
            heapResource = rm.claimMemoryResource(ResourceOwner.SYSTEM, start,
                    size, ResourceManager.MEMMODE_NORMAL);
        } catch (NameNotFoundException ex) {
            BootLogInstance.get().fatal("Cannot find resource manager", ex);
        } catch (ResourceNotFreeException ex) {
            BootLogInstance.get().fatal("Cannot claim available heap region", ex);
        }

    }

    public void notifyClassResolved(VmType< ? > vmType) {
        final MMType type;
        final boolean acyclic = false; // TODO understand me
        if (vmType.isArray()) {
            final VmArrayClass< ? > arrType = (VmArrayClass< ? >) vmType;
            type = new MMType(false, !arrType.isPrimitiveArray(), acyclic,
                    pickAllocatorForType(vmType), EMPY_INT_ARRAY);
        } else if (!vmType.isInterface()) {
            final VmNormalClass< ? > clsType = (VmNormalClass< ? >) vmType;
            type = new MMType(false, false, acyclic,
                    pickAllocatorForType(vmType), clsType.getReferenceOffsets());
        } else {
            type = null;
        }
        vmType.setMmType(type);
    }

    /**
     * Determine the default allocator to be used for a given type.
     *
     * @param type
     *            The type in question
     * @return The allocator to use for allocating instances of type
     *         <code>type</code>.
     */
    private static int pickAllocatorForType(VmType< ? > type) {
        int allocator = BasePlan.ALLOC_DEFAULT;
        final String clsName = type.getName();
        if (WITH_GCSPY) {
            if (clsName.startsWith("org.mmtk.vm.gcspy")
                    || clsName.startsWith("[Lorg.mmtk.vm.gcspy")) {
                allocator = BasePlan.ALLOC_GCSPY;
            }
        }
        if (clsName.startsWith("org.mmtk")
                || clsName.startsWith("org.jnode.vm.VmProcessor")) {
            allocator = BasePlan.ALLOC_IMMORTAL;
        }
        return allocator;
    }

    public void loadClasses(VmClassLoader loader) throws ClassNotFoundException {
        loader.loadClass("org.mmtk.vm.Plan", true);
        loader.loadClass("org.mmtk.vm.PlanConstants", true);
        loader.loadClass(MMType.class.getName(), true);
    }

    public void verifyBeforeEmit() {
        super.verifyBeforeEmit();
        Space.printVMMap();
    }

    /**
     * Call plan.alloc
     *
     * @param bytes
     * @param align
     * @param offset
     * @param allocator
     * @return the start address of the allocated memory region
     */
    protected abstract Address alloc(int bytes, int align, int offset,
            int allocator);

    /**
     * Call plan.postAlloc.
     *
     * @param object
     * @param typeRef
     * @param bytes
     * @param allocator
     */
    protected abstract void postAlloc(ObjectReference object,
            ObjectReference typeRef, int bytes, int allocator);

    /**
     * Call Plan.checkAllocator.
     *
     * @param bytes
     * @param align
     * @param allocator
     */
    protected abstract int checkAllocator(int bytes, int align, int allocator);

    /**
     * Call the boot method of the current plan.
     */
    protected abstract void bootPlan();
}
TOP

Related Classes of org.jnode.vm.memmgr.mmtk.BaseMmtkHeapManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.