Class.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    Copyright © 2021, 2024 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package avt.lang;

import avt.lang.array.*;
import platform.dependent.*;

public final class Class(RequiredReflectiveObject)
{
    public static final int CLASS     = 0x00;
    public static final int SERVICE   = 0x20;
    public static final int STRUCT    = 0x40;
    public static final int INTERFACE = 0x60;
    public static final int PRIMITIVE = 0x80;
    public static final int TYPE_MASK = 0xe0;

    public static final int VOID    =  8;
    public static final int BOOLEAN = 16;
    public static final int CHAR    = 20;
    public static final int BYTE    = 24;
    public static final int BYTE2   = 25;
    public static final int BYTE4   = 26;
    public static final int BYTE8   = 27;
    public static final int SHORT   = 28;
    public static final int SHORT2  = 29;
    public static final int SHORT4  = 30;
    public static final int SHORT8  = 31;
    public static final int INT     = 32;
    public static final int INT2    = 33;
    public static final int INT4    = 34;
    public static final int INT8    = 35;
    public static final int LONG    = 36;
    public static final int LONG2   = 37;
    public static final int LONG4   = 38;
    public static final int LONG8   = 39;
    public static final int FLOAT   = 40;
    public static final int FLOAT2  = 41;
    public static final int FLOAT4  = 42;
    public static final int FLOAT8  = 43;
    public static final int DOUBLE  = 44;
    public static final int DOUBLE2 = 45;
    public static final int DOUBLE4 = 46;
    public static final int DOUBLE8 = 47;
    public static final int REAL    = 48;

    private static final int NOT_INITIALIZED = 0;
    private static final int INITIALIZING    = 1;
    private static final int INITIALIZED     = 3;

    public static Class get(String canonicalName) throws ClassNotFoundException {
        if(canonicalName == null || canonicalName.isEmpty())
        {
            throw new ClassNotFoundException(package.getResourceString("not-found.class.empty"));
        }
        int dotPosition = canonicalName.lastIndexOf('.');
        Package parentPackage = Package.find(dotPosition < 0 ? null : canonicalName.substring(0, dotPosition));
        label0: if(parentPackage != null)
        {
            String simpleName = canonicalName.substring(dotPosition + 1);
            Class result = parentPackage.findDeclaredType(simpleName);
            if(result != null) return result;
            int bracketPosition = simpleName.indexOf("[]");
            if(bracketPosition > 0 && (result = parentPackage.findDeclaredType(simpleName.substring(0, bracketPosition))) != null)
            {
                for(Class arrayType; (arrayType = parentPackage.findDeclaredType(simpleName.substring(0, bracketPosition += 2))) != null; result = arrayType)
                {
                    if(!simpleName.startsWith("[]", bracketPosition)) break label0;
                }
                int nameLength = simpleName.length;
                Mutex operation = Runtime.getInstance().systemOperation;
                operation.lock();
                try
                {
                    for(Class arrayType; (arrayType = parentPackage.findAddedArrayType(result)) != null; bracketPosition += 2)
                    {
                        result = arrayType;
                        if(bracketPosition >= nameLength) return result;
                        if(!simpleName.startsWith("[]", bracketPosition)) break label0;
                    }
                    for(; ; bracketPosition += 2)
                    {
                        result = createArrayType(result, parentPackage);
                        if(bracketPosition >= nameLength) return result;
                        if(!simpleName.startsWith("[]", bracketPosition)) break label0;
                    }
                } finally
                {
                    operation.unlock();
                }
            }
        }
        throw new ClassNotFoundException(String.format(package.getResourceString("not-found.class.name"), new Object[] { canonicalName }));
    }

    private static native void fillArrayType(Class arrayType, Class superType, Class componentType, Package parentPackage);

    private static Class createArrayType(Class componentType, Package parentPackage) {
        String simpleName = componentType.simpleName;
        String canonicalName = parentPackage.canonicalName;
        canonicalName = String.format(canonicalName.isEmpty() ? "%1%[]" : "%0%.%1%[]", new Object[] { canonicalName, simpleName });
        final Class superType = Object[].class;
        final Class result = (Class) Runtime.getInstance().allocateInstance(
            Class.class, Class.class.fldInstanceSize + (superType.fldVirtualsCount + superType.fldSuperServicesCount << 3 | superType.fldInstanceReferencedFieldsCount << 2), -1, false
        );
        fillArrayType(result, superType, componentType, parentPackage);
        result.fldCanonicalName = canonicalName;
        result.fldSimpleName = canonicalName.substring(canonicalName.length - simpleName.length - 2);
        parentPackage.addArrayType(result);
        return result;
    }

    private static native Measureable mapArray(Object array, long pointer);

    private static native Struct mapStruct(Object struc, long pointer);

    private final int fldInstanceSize;
    private final int fldStructSize;
    private final int fldInstanceReferencedFieldsCount;
    private final int fldVirtualsCount;
    private final int fldImplementorsCount;
    private final int fldSuperServicesCount;
    private final int fldStructReferencedFieldsCount;
    private final int fldDeclaredFieldsCount;
    private final int fldDeclaredMethodsCount;
    private final int fldDeclaredPropertiesCount;
    private final int fldInstanceReferencedFieldsOffset;
    private final int fldVirtualsOffset;
    private final int fldImplementorsOffset;
    private final int fldSuperServicesOffset;
    private final int fldStructReferencedFieldsOffset;
    private final int fldDeclaredFieldsOffset;
    private final int fldDeclaredMethodsOffset;
    private final int fldDeclaredPropertiesOffset;
    private final int fldDefaultConstructorAttributes;
    private final int fldReserved74;
    private final int fldReserved78;
    private final int fldReserved7C;
    private final long fldSuperTypeOffset;
    private final long fldComponentTypeOffset;
    private final long fldParentPackageOffset;
    private final long fldDefaultConstructorOffset;
    private final long fldReservedA0;
    private final long fldReservedA8;
    private final long fldSourceFileNameOffset;
    private final int fldPrimitiveKind;
    private final int fldRequiredReflectiveObjectSize;
    private int fldReservedC0;
    private int fldClinitStatus;
    private Class[] fldSuperServices;
    private Object fldClinitMonitor;
    private Thread fldClinitThread;
    private String fldSimpleName;
    private String fldCanonicalName;
    private String fldSourceFullFileName;
    private String fldSourceSimpleFileName;

    private () {  }

    public String toString() {
        String type;
        switch((fldAttributes & TYPE_MASK) >> 5)
        {
        case SERVICE >> 5:
            type = "service ";
            break;
        case STRUCT >> 5:
            type = "struct ";
            break;
        case INTERFACE >> 5:
            type = "interface ";
            break;
        case PRIMITIVE >> 5:
            type = "primitive ";
            break;
        default:
            type = "class ";
        }
        return type + getCanonicalName();
    }

    public boolean isArray() { return fldComponentTypeOffset != 0L; }

    public boolean isClass() { return (fldAttributes & TYPE_MASK) == CLASS; }

    public boolean isStruct() { return (fldAttributes & TYPE_MASK) == STRUCT; }

    public boolean isService() { return (fldAttributes & (SERVICE | PRIMITIVE)) == SERVICE; }

    public boolean isInterface() { return (fldAttributes & TYPE_MASK) == INTERFACE; }

    public boolean isPrimitive() { return (fldAttributes & TYPE_MASK) == PRIMITIVE; }

    public boolean isScalar() { return (fldAttributes & TYPE_MASK) == PRIMITIVE && (fldPrimitiveKind & 3) == 0; }

    public boolean isVector() { return (fldPrimitiveKind & 3) != 0; }

    public boolean isAssignableFrom(Class type) {
        if(type == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "type" }));
        }
        if(type == this)
        {
            return true;
        }
        int attributes = type.fldAttributes;
        if((attributes & TYPE_MASK) == PRIMITIVE | ((attributes = fldAttributes) & TYPE_MASK) == PRIMITIVE)
        {
            /* type.isPrimitive() | this.isPrimitive() */
            return false;
        }
        if(fldComponentTypeOffset == 0L)
        {
            /* !this.isArray() */
            return (attributes & (SERVICE | PRIMITIVE)) == SERVICE ? type.isServiceImplements(this) : type.isInheritedFrom(this);
        }
        Class thisComponent = this.getComponentType();
        Class typeComponent = type.getComponentType();
        for(Class component = thisComponent.getComponentType(); component != null; component = component.getComponentType())
        {
            if(typeComponent == null)
            {
                return false;
            }
            thisComponent = component;
            typeComponent = typeComponent.getComponentType();
        }
        return typeComponent != null && thisComponent.isAssignableFrom(typeComponent);
    }

    public boolean isInstance(Object instance) {
        return instance != null && isAssignableFrom(instance.getClass());
    }

    public int getArrayDimensionsQuantity() {
        int result = 0;
        for(Class component = getComponentType(); component != null; component = component.getComponentType()) result++;
        return result;
    }

    public Class getArrayCellType() {
        Class result = null;
        for(Class component = getComponentType(); component != null; component = component.getComponentType()) result = component;
        return result;
    }

    public Object cast(Object instance) {
        Class source;
        if(instance != null && !isAssignableFrom(source = instance.getClass()))
        {
            throw new ClassCastException(package.getResourceString("class-cast")) { source = source, destination = this };
        }
        return instance;
    }

    public Object newInstance() throws InstantiationException, IllegalAccessException {
        int attributes = fldAttributes;
        int kind = attributes & TYPE_MASK;
        if(fldComponentTypeOffset != 0L || kind == INTERFACE || kind == PRIMITIVE || (attributes & ABSTRACT) != 0)
        {
            throw new InstantiationException(package.getResourceString("instantiation.object")) { type = this };
        }
        if(fldDefaultConstructorOffset == 0L)
        {
            throw new InstantiationException(package.getResourceString("instantiation.constructor")) { type = this };
        }
        label0:
        {
            boolean isVisible = true;
            switch(attributes & VISIBILITY_MASK)
            {
            case DEFAULT:
                Class type = Thread.callerTypeTrace();
                isVisible = parentPackage == type.parentPackage && sourceSimpleFileName.equals(type.sourceSimpleFileName);
                break;
            case PACKAGE:
                Class type = Thread.callerTypeTrace();
                isVisible = parentPackage == type.parentPackage;
                break;
            default:
                break label0;
            }
            if(!isVisible)
            {
                throw new IllegalAccessException(String.format(package.getResourceString("illegal-access.type"), new Object[] { getCanonicalName() }));
            }
        }
        attributes = fldDefaultConstructorAttributes;
        label0:
        {
            boolean isVisible = true;
            switch(attributes & VISIBILITY_MASK)
            {
            case PRIVATE:
                Class type = Thread.callerTypeTrace();
                Class parent = kind == SERVICE ? getSuperClass() : kind == STRUCT ? Struct.class : this;
                isVisible = parent == type && type == this;
                break;
            case DEFAULT:
                Class type = Thread.callerTypeTrace();
                Class parent = kind == SERVICE ? getSuperClass() : kind == STRUCT ? Struct.class : this;
                Object packag = type.parentPackage;
                Object source = type.sourceSimpleFileName;
                if(packag != parentPackage || !source.equals(sourceSimpleFileName))
                {
                    isVisible = false;
                    break;
                }
                for(int length = fldSuperServicesCount, int index = -1, Class current = getSuperClass(); current != null; )
                {
                    if(parent.isAssignableFrom(current) && current.isAssignableFrom(this) && (packag != current.parentPackage || !source.equals(current.sourceSimpleFileName)))
                    {
                        isVisible = false;
                        break;
                    }
                    if(index >= 0 || (current = current.getSuperClass()) == null) current = ++index >= length ? null : getSuperService(index);
                }
                break;
            case PACKAGE:
                Class type = Thread.callerTypeTrace();
                Class parent = kind == SERVICE ? getSuperClass() : kind == STRUCT ? Struct.class : this;
                Object packag = type.parentPackage;
                if(packag != parentPackage)
                {
                    isVisible = false;
                    break;
                }
                for(int length = fldSuperServicesCount, int index = -1, Class current = getSuperClass(); current != null; )
                {
                    if(parent.isAssignableFrom(current) && current.isAssignableFrom(this) && (packag != current.parentPackage))
                    {
                        isVisible = false;
                        break;
                    }
                    if(index >= 0 || (current = current.getSuperClass()) == null) current = ++index >= length ? null : getSuperService(index);
                }
                break;
            case PROTECTED:
                Class type = Thread.callerTypeTrace();
                Class parent = kind == SERVICE ? getSuperClass() : kind == STRUCT ? Struct.class : this;
                isVisible = parent.isAssignableFrom(type) && type.isAssignableFrom(this) || parent.parentPackage == type.parentPackage;
                break;
            default:
                break label0;
            }
            if(!isVisible)
            {
                throw new IllegalAccessException(String.format(package.getResourceString("illegal-access.constructor"), new Object[] { getCanonicalName() + "()" }));
            }
        }
        Object result = allocateInstance();
        result.defaultConstructor();
        result.afterConstruction();
        return result;
    }

    public Measureable newArray(int length) throws InstantiationException, IllegalAccessException {
        if(fldComponentTypeOffset == 0L)
        {
            throw new InstantiationException(package.getResourceString("instantiation.array")) { type = this };
        }
        int attributes = fldAttributes;
        label0:
        {
            boolean isVisible = true;
            switch(attributes & VISIBILITY_MASK)
            {
            case DEFAULT:
                Class type = Thread.callerTypeTrace();
                isVisible = parentPackage == type.parentPackage && sourceSimpleFileName.equals(type.sourceSimpleFileName);
                break;
            case PACKAGE:
                Class type = Thread.callerTypeTrace();
                isVisible = parentPackage == type.parentPackage;
                break;
            default:
                break label0;
            }
            if(!isVisible)
            {
                throw new IllegalAccessException(String.format(package.getResourceString("illegal-access.type"), new Object[] { getCanonicalName() }));
            }
        }
        return allocateArray(length);
    }

    public Measureable newArray(int[] lengths) throws InstantiationException, IllegalAccessException {
        int length;
        long componentTypeOffset;
        if(lengths == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "lengths" }));
        }
        if((length = lengths.length) < 1)
        {
            throw new IllegalArgumentException(String.format(package.getResourceString("illegal-argument.array-dimensions.empty"), new Object[] { "lengths" }));
        }
        if((componentTypeOffset = fldComponentTypeOffset) != 0L && length > getArrayDimensionsQuantity())
        {
            throw new IllegalArgumentException(String.format(package.getResourceString("illegal-argument.array-dimensions.too-long"), new Object[] { "lengths" }));
        }
        if(componentTypeOffset == 0L)
        {
            throw new InstantiationException(package.getResourceString("instantiation.array")) { type = this };
        }
        int attributes = fldAttributes;
        label0:
        {
            boolean isVisible = true;
            switch(attributes & VISIBILITY_MASK)
            {
            case DEFAULT:
                Class type = Thread.callerTypeTrace();
                isVisible = parentPackage == type.parentPackage && sourceSimpleFileName.equals(type.sourceSimpleFileName);
                break;
            case PACKAGE:
                Class type = Thread.callerTypeTrace();
                isVisible = parentPackage == type.parentPackage;
                break;
            default:
                break label0;
            }
            if(!isVisible)
            {
                throw new IllegalAccessException(String.format(package.getResourceString("illegal-access.type"), new Object[] { getCanonicalName() }));
            }
        }
        Array.copy(lengths, 0, lengths = new int[length], 0, length);
        return allocateArray(lengths);
    }

    public Measureable newArrayAt(long pointer, int length) throws InstantiationException, IllegalAccessException {
        Class componentType = getComponentType();
        if(componentType == null)
        {
            throw new InstantiationException(package.getResourceString("instantiation.array")) { type = this };
        }
        if((componentType.fldAttributes & TYPE_MASK) != PRIMITIVE)
        {
            throw new InstantiationException(package.getResourceString("instantiation.primitive")) { type = this };
        }
        int attributes = fldAttributes;
        label0:
        {
            boolean isVisible = true;
            switch(attributes & VISIBILITY_MASK)
            {
            case DEFAULT:
                Class type = Thread.callerTypeTrace();
                isVisible = parentPackage == type.parentPackage && sourceSimpleFileName.equals(type.sourceSimpleFileName);
                break;
            case PACKAGE:
                Class type = Thread.callerTypeTrace();
                isVisible = parentPackage == type.parentPackage;
                break;
            default:
                break label0;
            }
            if(!isVisible)
            {
                throw new IllegalAccessException(String.format(package.getResourceString("illegal-access.type"), new Object[] { getCanonicalName() }));
            }
        }
        if(length < 0)
        {
            throw new NegativeArrayLengthException(package.getResourceString("negative-array-length"));
        }
        long limit = pointer + componentType.fldInstanceSize * (long) length;
        Runtime runtime = Runtime.getInstance();
        if(!runtime.isCanonicalPointer(pointer))
        {
            throw new SecurityException(String.format(package.getResourceString("security.pointer"), new Object[] { Long.toHexString(pointer) }));
        }
        if(!runtime.isCanonicalPointer(limit - 1))
        {
            throw new SecurityException(String.format(package.getResourceString("security.pointer"), new Object[] { Long.toHexString(limit - 1) }));
        }
        if(runtime.isProtectedMemory(new long2 { pointer, limit }))
        {
            throw new SecurityException(String.format(package.getResourceString("security.memory"), new Object[] { Long.toHexString(pointer), Long.toHexString(limit) }));
        }
        return mapArray(runtime.allocateInstance(this, fldInstanceSize, length, false), pointer);
    }

    public Struct newStructAt(long pointer) throws InstantiationException, IllegalAccessException {
        int attributes = fldAttributes;
        if((attributes & TYPE_MASK) != STRUCT)
        {
            throw new InstantiationException(package.getResourceString("instantiation.struct")) { type = this };
        }
        label0:
        {
            boolean isVisible = true;
            switch(attributes & VISIBILITY_MASK)
            {
            case DEFAULT:
                Class type = Thread.callerTypeTrace();
                isVisible = parentPackage == type.parentPackage && sourceSimpleFileName.equals(type.sourceSimpleFileName);
                break;
            case PACKAGE:
                Class type = Thread.callerTypeTrace();
                isVisible = parentPackage == type.parentPackage;
                break;
            default:
                break label0;
            }
            if(!isVisible)
            {
                throw new IllegalAccessException(String.format(package.getResourceString("illegal-access.type"), new Object[] { getCanonicalName() }));
            }
        }
        long limit = pointer + fldStructSize;
        Runtime runtime = Runtime.getInstance();
        if(!runtime.isCanonicalPointer(pointer))
        {
            throw new SecurityException(String.format(package.getResourceString("security.pointer"), new Object[] { Long.toHexString(pointer) }));
        }
        if(limit - pointer > 1 && !runtime.isCanonicalPointer(limit - 1))
        {
            throw new SecurityException(String.format(package.getResourceString("security.pointer"), new Object[] { Long.toHexString(limit - 1) }));
        }
        if(runtime.isProtectedMemory(new long2 { pointer, limit }))
        {
            throw new SecurityException(String.format(package.getResourceString("security.memory"), new Object[] { Long.toHexString(pointer), Long.toHexString(limit) }));
        }
        Struct result = mapStruct(runtime.allocateInstance(this, fldInstanceSize, -1, false), pointer);
        result.afterConstruction();
        return result;
    }

    public String simpleName { read = getSimpleName }

    public String canonicalName { read = getCanonicalName }

    public int structSize { read = fldStructSize }

    public int instanceSize { read = fldInstanceSize }

    public int vectorLength { read = getVectorLength }

    public int primitiveKind { read = fldPrimitiveKind }

    public Class[] superServices { read = getSuperServices }

    public Class superClass { read = getSuperClass }

    public Class vectorBase { read = getVectorBase }

    public Class componentType { read = getComponentType }

    public String sourceFullFileName { read = getSourceFullFileName }

    public String sourceSimpleFileName { read = getSourceSimpleFileName }

    public Package parentPackage { read = getParentPackage }

    package native int4 getStructReferencedFieldInfo(int index);

    package native Class getStructReferencedFieldType(int index);

    package int structReferencedFieldsCount { read = fldStructReferencedFieldsCount }

    private void clinitUnlock() {
        Runtime runtime = Runtime.getInstance();
        if(!runtime.multiThreaded)
        {
            fldClinitStatus = INITIALIZED;
            fldClinitMonitor = null;
            fldClinitThread = null;
            return;
        }
        Object monitor = null;
        Mutex operation = runtime.systemOperation;
        operation.lock();
        try
        {
            monitor = fldClinitMonitor;
            fldClinitStatus = INITIALIZED;
            fldClinitMonitor = null;
            fldClinitThread = null;
        } finally
        {
            operation.unlock();
        }
        if(monitor != null) synchronized(monitor)
        {
            monitor.notifyAll();
        }
    }

    private boolean clinitTryLock() {
        if(fldClinitStatus == INITIALIZED) return false;
        Runtime runtime = Runtime.getInstance();
        if(!runtime.multiThreaded)
        {
            if(fldClinitStatus == INITIALIZING)
            {
                return false;
            }
            fldClinitStatus = INITIALIZING;
            return true;
        }
        int result = 0;
        Object monitor = null;
        Mutex operation = runtime.systemOperation;
        operation.lock();
        try
        {
            switch(fldClinitStatus)
            {
            case NOT_INITIALIZED:
                fldClinitThread = Thread.current();
                fldClinitStatus = INITIALIZING;
                break;
            case INITIALIZING:
                if(fldClinitThread != Thread.current())
                {
                    if((monitor = fldClinitMonitor) == null) fldClinitMonitor = monitor = new Object();
                    result = 1;
                    break;
                }
                /* падение через */
            default:
                result = -1;
            }
        } finally
        {
            operation.unlock();
        }
        if(result == 1) synchronized(monitor)
        {
            do
            {
                try
                {
                    monitor.wait(10);
                }
                catch(InterruptedException exception)
                {
                    exception.printStackTrace();
                }
            } while(fldClinitStatus < INITIALIZED);
        }
        return result == 0;
    }

    private boolean isInheritedFrom(Class type) {
        for(Class current = getSuperClass(); current != null; current = current.getSuperClass()) if(current == type) return true;
        return false;
    }

    private boolean isServiceImplements(Class type) {
        for(int index = fldSuperServicesCount; index-- > 0; ) if(getSuperService(index) == type) return true;
        return false;
    }

    private int getVectorLength() {
        int kind = fldPrimitiveKind;
        return kind <= VOID ? 0 : 1 << (kind & 3);
    }

    private native long getSourceFileNamePointer();

    private native long getServiceMethodEntryPoint(Class type, int offset);

    private Class[] getSuperServices() {
        Class[] result = fldSuperServices;
        if(result == null)
        {
            int length = fldSuperServicesCount;
            result = new Class[length];
            for(int index = length; index-- > 0; ) result[index] = getSuperService(index);
            result.finalize();
            fldSuperServices = result;
        }
        return result;
    }

    private native Class getSuperService(int index);

    private native Class getSuperClass();

    private Class getVectorBase() {
        switch(fldPrimitiveKind >> 2)
        {
        case VOID >> 2:
            return void.class;
        case BOOLEAN >> 2:
            return boolean.class;
        case CHAR >> 2:
            return char.class;
        case BYTE >> 2:
            return byte.class;
        case SHORT >> 2:
            return short.class;
        case INT >> 2:
            return int.class;
        case LONG >> 2:
            return long.class;
        case FLOAT >> 2:
            return float.class;
        case DOUBLE >> 2:
            return double.class;
        case REAL >> 2:
            return real.class;
        default:
            return null;
        }
    }

    private native Class getComponentType();

    private String getSimpleName() {
        String result = fldSimpleName;
        return result != null ? result : fldSimpleName = String.getConstant(fldNameIndex);
    }

    private String getCanonicalName() {
        String result = fldCanonicalName;
        if(result != null) return result;
        String canonicalName = getParentPackage().canonicalName;
        return fldCanonicalName = String.format(canonicalName == null || canonicalName.isEmpty() ? "%1%" : "%0%.%1%", new Object[] { canonicalName, String.getConstant(fldNameIndex) });
    }

    private String getSourceFullFileName() {
        String result = fldSourceFullFileName;
        if(result != null) return result;
        long sourceFileNamePointer = getSourceFileNamePointer();
        return fldSourceFullFileName = sourceFileNamePointer == 0L ? "" : DebugInfo.getSourceFileNameString(sourceFileNamePointer);
    }

    private String getSourceSimpleFileName() {
        String result = fldSourceSimpleFileName;
        return result != null ? result : fldSourceSimpleFileName = (result = getSourceFullFileName()).substring(result.lastIndexOf('/') + 1);
    }

    private native Package getParentPackage();

    private Object allocateInstance() {
        return Runtime.getInstance().allocateInstance(this, (fldAttributes & TYPE_MASK) == STRUCT ? fldInstanceSize + (long) fldStructSize : fldInstanceSize, -1, false);
    }

    private Measureable allocateArray(int length) {
        if(length < 0)
        {
            throw new NegativeArrayLengthException(package.getResourceString("negative-array-length"));
        }
        Runtime runtime = Runtime.getInstance();
        Class componentType = getComponentType();
        return (Measureable) runtime.allocateInstance(
            this, fldInstanceSize + ((componentType.fldAttributes & TYPE_MASK) == PRIMITIVE ? componentType.fldInstanceSize : runtime.processorCodeBits >> 3) * (long) length, length, false
        );
    }

    private Measureable allocateArray(int[] lengths) {
        for(int index = lengths.length; index-- > 0; ) if(lengths[index] < 0)
        {
            throw new NegativeArrayLengthException(package.getResourceString("negative-array-length"));
        }
        return allocateSubarray(lengths, 0);
    }

    private Measureable allocateSubarray(int[] lengths, int index) {
        int length = lengths[index++];
        Measureable result = allocateArray(length);
        if(index < lengths.length) for(Object[] subarray = (Object[]) result, Class subtype = getComponentType(), int sai = length; sai-- > 0; )
        {
            subarray[sai] = subtype.allocateSubarray(lengths, index);
        }
        return result;
    }
}