Package org.jnode.vm.classmgr

Source Code of org.jnode.vm.classmgr.VmStatics

/*
* $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.classmgr;

import java.io.PrintWriter;
import java.nio.ByteOrder;

import org.jnode.annotation.MagicPermission;
import org.jnode.assembler.Label;
import org.jnode.assembler.ObjectResolver;
import org.jnode.vm.VmAddress;
import org.jnode.vm.facade.ObjectVisitor;
import org.jnode.vm.facade.VmArchitecture;
import org.jnode.vm.facade.VmUtils;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.ObjectReference;
import org.vmmagic.unboxed.UnboxedObject;

/**
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
@MagicPermission
public abstract class VmStatics extends VmStaticsBase {

    private int[] statics;
    private transient Object[] objects;
    private final int slotLength;
    private final boolean lsbFirst;
    private transient ObjectResolver resolver;
    private transient boolean locked;
    private final VmStaticsAllocator allocator;

    /**
     * Initialize this instance
     */
    public VmStatics(VmArchitecture arch, ObjectResolver resolver, int size) {
        this(new VmStaticsAllocator(size), arch, resolver);
    }

    /**
     * Initialize this instance
     */
    protected VmStatics(VmStaticsAllocator allocator, VmArchitecture arch, ObjectResolver resolver) {
        this.statics = new int[allocator.getCapacity()];
        this.allocator = allocator;
        this.objects = new Object[allocator.getCapacity()];
        this.lsbFirst = (arch.getByteOrder() == ByteOrder.LITTLE_ENDIAN);
        this.slotLength = arch.getReferenceSize() >> 2;
        this.resolver = resolver;
    }

    /**
     * Allocate an int/float type entry.
     *
     * @return the index of the allocated entry.
     */
    final int allocIntField() {
        return allocator.alloc(TYPE_INT, 1);
    }

    /**
     * Allocate an long/double type entry.
     *
     * @return the index of the allocated entry.
     */
    final int allocLongField() {
        return allocator.alloc(TYPE_LONG, 2);
    }

    /**
     * Allocate an Object type entry.
     *
     * @return the index of the allocated entry.
     */
    final int allocObjectField() {
        return allocator.alloc(TYPE_OBJECT, slotLength);
    }

    /**
     * Allocate an String type entry.
     *
     * @return the index of the allocated entry.
     */
    final int allocConstantStringField(String value) {
        final int idx = allocator.alloc(TYPE_STRING, slotLength);
        setRawObject(idx, value);
        return idx;
    }

    /**
     * Allocate an org.jnode.vm.Address type entry.
     *
     * @return the index of the allocated entry.
     */
    public final int allocAddressField() {
        return allocator.alloc(TYPE_ADDRESS, slotLength);
    }

    /**
     * Allocate an method code type entry.
     *
     * @return the index of the allocated entry.
     */
    final int allocMethodCode() {
        final int idx = allocator.alloc(TYPE_METHOD_CODE, slotLength);
        return idx;
    }

    /**
     * Set the pointer of the native code of a method in the table at the given index.
     *
     * @param idx
     * @param nativeCode
     */
    final void setMethodCode(int idx, VmAddress nativeCode) {
        allocator.testType(idx, TYPE_METHOD_CODE);
        setRawObject(idx, nativeCode);
    }

    /**
     * Allocate an {@link org.jnode.vm.classmgr.VmType} type entry.
     *
     * @return the index of the allocated entry.
     */
    final int allocClass(VmType type) {
        final int idx = allocator.alloc(TYPE_CLASS, slotLength);
        setRawObject(idx, type);
        return idx;
    }

    /**
     * Gets the type at the given index.
     *
     * @param idx
     * @return the type entry
     */
    final VmType getTypeEntry(int idx) {
        allocator.testType(idx, TYPE_CLASS);
        return (VmType) getRawObject(idx);
    }

    /**
     * Get a String entry at the given index.
     *
     * @param idx
     * @return the string
     */
    public final String getStringEntry(int idx) {
        allocator.testType(idx, TYPE_STRING);
        return (String) getRawObject(idx);
    }

    public final void setInt(int idx, int value) {
        allocator.testType(idx, TYPE_INT);
        if (statics[idx] != value) {
            if (locked) {
                throw new RuntimeException("Locked");
            }
            statics[idx] = value;
        }
    }

    public final int getInt(int idx) {
        allocator.testType(idx, TYPE_INT);
        return statics[idx];
    }

    public final void setObject(int idx, Object value) {
        allocator.testType(idx, TYPE_OBJECT);
        if (setRawObject(idx, value)) {
            if (locked) {
                throw new RuntimeException("Locked");
            }
        }
    }

    public final void setAddress(int idx, Label value) {
        if (!VmUtils.isWritingImage()) {
            throw new IllegalStateException("Only allowed during bootimage creation.");
        }
        allocator.testType(idx, TYPE_ADDRESS);
        if (setRawObject(idx, value)) {
            if (locked) {
                throw new RuntimeException("Locked");
            }
        }
    }

    public final void setAddress(int idx, UnboxedObject value) {
        if (!VmUtils.isWritingImage()) {
            throw new IllegalStateException("Only allowed during bootimage creation.");
        }
        allocator.testType(idx, TYPE_ADDRESS);
        if (setRawObject(idx, value)) {
            if (locked) {
                throw new RuntimeException("Locked");
            }
        }
    }

    /*final void setMethod(int idx, VmMethod value) {
         if (locked) {
             throw new RuntimeException("Locked");
         }
         if (types[idx] != TYPE_METHOD) {
             throw new IllegalArgumentException("Type error " + types[idx]);
         }
         setRawObject(idx, value);
     }*/

    private final boolean setRawObject(int idx, Object value) {
        if (objects != null) {
            if (objects[idx] != value) {
                objects[idx] = value;
                return true;
            } else {
                return false;
            }
        } else {
            final Address valuePtr = ObjectReference.fromObject(value).toAddress();
            if (slotLength == 1) {
                statics[idx] = valuePtr.toInt();
            } else {
                final long lvalue = valuePtr.toLong();
                if (lsbFirst) {
                    statics[idx + 0] = (int) (lvalue & 0xFFFFFFFFL);
                    statics[idx + 1] = (int) ((lvalue >>> 32) & 0xFFFFFFFFL);
                } else {
                    statics[idx + 1] = (int) (lvalue & 0xFFFFFFFFL);
                    statics[idx + 0] = (int) ((lvalue >>> 32) & 0xFFFFFFFFL);
                }
            }
            return true;
        }
    }

    private final Object getRawObject(int idx) {
        if (objects != null) {
            return objects[idx];
        } else {
            final Address ptr;
            if (slotLength == 1) {
                ptr = Address.fromIntZeroExtend(statics[idx]);
            } else {
                final long lsb;
                final long msb;
                if (lsbFirst) {
                    lsb = statics[idx + 0] & 0xFFFFFFFFL;
                    msb = statics[idx + 1] & 0xFFFFFFFFL;
                } else {
                    lsb = statics[idx + 1] & 0xFFFFFFFFL;
                    msb = statics[idx + 0] & 0xFFFFFFFFL;
                }
                ptr = Address.fromLong(lsb | (msb << 32));
            }
            return ptr.toObjectReference().toObject();
        }
    }

    public final void setLong(int idx, long value) {
        if (locked) {
            throw new RuntimeException("Locked");
        }
        allocator.testType(idx, TYPE_LONG);
        if (lsbFirst) {
            statics[idx + 0] = (int) (value & 0xFFFFFFFFL);
            statics[idx + 1] = (int) ((value >>> 32) & 0xFFFFFFFFL);
        } else {
            statics[idx + 1] = (int) (value & 0xFFFFFFFFL);
            statics[idx + 0] = (int) ((value >>> 32) & 0xFFFFFFFFL);
        }
    }

    /**
     * Get the full statics table.
     *
     * @return The statics table.
     */
    public final Object getTable() {
        return statics;
    }

    /**
     * Get the statics type at a given index
     *
     * @return int
     */
    public final int getType(int index) {
        return allocator.getType(index);
    }

    /**
     * Let all objects in this statics-table make a visit to the given visitor.
     *
     * @param visitor
     */
    public boolean walk(ObjectVisitor visitor) {
        return walk(TYPE_OBJECT, visitor);
    }

    /**
     * Let all objects in this statics-table make a visit to the given visitor.
     *
     * @param visitor
     * @return false if the last visit returned false, true otherwise.
     */
    private boolean walk(int visitType, ObjectVisitor visitor) {
        final int[] table;
        final byte[] types;
        final int length;
        table = this.statics;
        types = allocator.getTypes();
        length = allocator.getLength();
        if (slotLength == 1) {
            for (int i = 0; i < length; i++) {
                final byte type = types[i];
                if (type == visitType) {
                    final Object object;
                    object = Address.fromIntZeroExtend(table[i]).toObjectReference().toObject();
                    if (object != null) {
                        final boolean rc = visitor.visit(object);
                        if (!rc) {
                            return false;
                        }
                    }
                }
            }
        } else {
            for (int i = 0; i < length; i++) {
                final byte type = types[i];
                if (type == visitType) {
                    final Object object;
                    final long lsb = table[i + 0] & 0xFFFFFFFFL;
                    final long msb = table[i + 1] & 0xFFFFFFFFL;
                    i++;
                    object = Address.fromLong(lsb | (msb << 32)).toObjectReference().toObject();
                    if (object != null) {
                        final boolean rc = visitor.visit(object);
                        if (!rc) {
                            return false;
                        }
                    }
                }
            }
        }
        return true;
    }

    public final void dumpStatistics(PrintWriter out) {
        allocator.dumpStatistics(out);
    }

    /**
     * @see org.jnode.vm.objects.VmSystemObject#verifyBeforeEmit()
     */
    public void verifyBeforeEmit() {
        //System.out.println("VmStatics#verifyBeforeEmit " + slotLength + ", " + resolver);
        final int max = statics.length;
        int count = 0;
        for (int i = 0; i < max; i++) {
            final Object value = objects[i];
            if (value != null) {
                count++;
                if (slotLength == 1) {
                    statics[i] = resolver.addressOf32(value);
                    if ((statics[i] == 0) && (allocator.getType(i) != TYPE_ADDRESS)) {
                        throw new RuntimeException("addressof32(" + value + ") is null");
                    }
                } else {
                    final long lvalue = resolver.addressOf64(value);
                    if ((lvalue == 0L) && (allocator.getType(i) != TYPE_ADDRESS)) {
                        throw new RuntimeException("addressof64(" + value + ") is null");
                    }
                    if (lsbFirst) {
                        statics[i + 0] = (int) (lvalue & 0xFFFFFFFFL);
                        statics[i + 1] = (int) ((lvalue >>> 32) & 0xFFFFFFFFL);
                    } else {
                        statics[i + 1] = (int) (lvalue & 0xFFFFFFFFL);
                        statics[i + 0] = (int) ((lvalue >>> 32) & 0xFFFFFFFFL);
                    }
                }
            } else if (allocator.getType(i) == TYPE_METHOD_CODE) {
                throw new RuntimeException("Method is null");
            }
        }
        objects = null;
        locked = true;
        //System.out.println("VmStatics#verifyBeforeEmit count=" + count);
    }

    /**
     * Gets my statics allocator.
     *
     * @return the allocator
     */
    protected final VmStaticsAllocator getAllocator() {
        return allocator;
    }
}
TOP

Related Classes of org.jnode.vm.classmgr.VmStatics

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.