Win32Runtime.avt

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

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

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

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

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

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

package platform.dependent.mswindows.runtime;

import avt.security.*;
import platform.dependent.mswindows.kernel.*;
import platform.independent.filesystem.*;

public final class Win32Runtime(Runtime)
{
    /*<fold вычисленные точкой входа размеры областей тагированного стака>*/
    public static final long TAGGED_STACK_DATA_AREA_SIZE;
    public static final long TAGGED_STACK_CONTEXT_AREA_SIZE;
    /*</fold>*/

    /*<fold атрибуты куч>*/
    private static final int NORMAL     = 0;
    private static final int EXECUTABLE = 1;
    /*</fold>*/

    /*<fold адресное пространство>*/
    private static final long PAGE_SIZE              = 0x0000000000001000L;
    private static final long ADDRESS_SPACE_CAPACITY = 0x0000800000000000L;
    /*</fold>*/

    /*<fold каталог куч>*/
    private static long heapsAligned;
    private static Heap64[] heapsCatalogue;
    /*</fold>*/

    /*<fold контекст безопасности вызывающего метода>*/
    private static CallerSecurityContext securityContext;
    /*</fold>*/

    public static void initialize() {
        protectProgrammeImportRegion();
        final long allocationSize = Heap64.MIN_ALLOC_SIZE;
        long heapsLength = ADDRESS_SPACE_CAPACITY / (allocationSize + getHeapSize(allocationSize));
        long heapsSize = heapsLength * long.class.instanceSize + Heap64[].class.instanceSize;
        long heapsPointer = Kernel.virtualAlloc(0, heapsAligned = heapsSize + (-heapsSize & PAGE_SIZE - 1), Kernel.MEM_COMMIT, Kernel.PAGE_READWRITE);
        (heapsCatalogue = (Heap64[]) initializeInstance(heapsPointer, Heap64[].class, Heap64[].class.instanceSize, (int) heapsLength, null)).length = 0;
        long runtimeSize = class.instanceSize;
        long runtimePointer = newHeap(Heap64.getAllocationSize(runtimeSize), NORMAL).allocate(runtimeSize);
        construct((Runtime) initializeInstance(runtimePointer, class, runtimeSize, -1, null));
        securityContext = new CallerSecurityContext();
    }

    public static void finalize() {
        destruct(securityContext);
    }

    package static CallerSecurityContext getSecurityContext() { return securityContext; }

    private static void protectProgrammeImportRegion() {
        long2 importRegionPointers = getProgrammeImportRegionPointers();
        long importRegionBeginPointer = importRegionPointers[0];
        long importRegionEndPointer = importRegionPointers[1];
        Kernel.virtualProtect(importRegionBeginPointer, importRegionEndPointer - importRegionBeginPointer + (-importRegionEndPointer & PAGE_SIZE - 1), Kernel.PAGE_READONLY);
    }

    private static int4 getOperatingSystemVersion() {
        try
        {
            KUSER_SHARED_DATA kuser = (KUSER_SHARED_DATA) KUSER_SHARED_DATA.class.newStructAt(0x7ffe0000L);
            return new int4 { kuser.ntMajorVersion, kuser.ntMinorVersion, kuser.ntBuildNumber, 0 };
        }
        catch(Exception exception)
        {
            throw exception instanceof RuntimeException ? (RuntimeException) exception : new RuntimeException(exception.message, exception);
        }
    }

    private static long getHeapSize(long allocationSize) {
        long heapAligned = (long) Heap64.class.instanceSize;
        long mmapAligned = (long) Heap64.getMemoryMapLength(allocationSize) * int4.class.instanceSize + int4[].class.instanceSize;
        heapAligned += -heapAligned & Heap64.BLOCK_SIZE - 1;
        mmapAligned += -mmapAligned & Heap64.BLOCK_SIZE - 1;
        long infoSize = heapAligned + mmapAligned;
        return infoSize + (-infoSize & PAGE_SIZE - 1);
    }

    private static native long getThreadEntryPoint();

    private static native long2 getProgrammeImportRegionPointers();

    private static Heap64 newHeap(long allocationSize, int attributes) {
        boolean isExecutable = (attributes & EXECUTABLE) != 0;
        int mmapLength = Heap64.getMemoryMapLength(allocationSize);
        long heapSize = (long) Heap64.class.instanceSize;
        long mmapSize = (long) mmapLength * int4.class.instanceSize + int4[].class.instanceSize;
        long heapAligned = heapSize + (-heapSize & Heap64.BLOCK_SIZE - 1);
        long mmapAligned = mmapSize + (-mmapSize & Heap64.BLOCK_SIZE - 1);
        long infoSize = heapAligned + mmapAligned;
        infoSize += -infoSize & PAGE_SIZE - 1;
        long heapPointer = Kernel.virtualAlloc(0, isExecutable ? infoSize : infoSize + allocationSize, Kernel.MEM_COMMIT, Kernel.PAGE_READWRITE);
        long dataPointer = !isExecutable ? heapPointer + infoSize : Kernel.virtualAlloc(0, allocationSize, Kernel.MEM_COMMIT, Kernel.PAGE_EXECUTE_READWRITE);
        if(heapPointer == 0)
        {
            if(isExecutable && dataPointer != 0) Kernel.virtualFree(dataPointer, 0, Kernel.MEM_RELEASE);
            return null;
        }
        if(dataPointer == 0)
        {
            Kernel.virtualFree(heapPointer, 0, Kernel.MEM_RELEASE);
            return null;
        }
        long mmapPointer = heapPointer + heapAligned;
        int4[] memoryMap = (int4[]) initializeInstance(mmapPointer, int4[].class, int4[].class.instanceSize, mmapLength, securityContext);
        Heap64 result = (Heap64) initializeInstance(heapPointer, Heap64.class, heapSize, -1, securityContext);
        constructInstance(result, securityContext);
        result.initialize(dataPointer, attributes, memoryMap);
        int length = heapsCatalogue.length;
        heapsCatalogue.length = length + 1;
        return heapsCatalogue[length] = result;
    }

    private int[] fldGarbageCollectorIndices;
    private long[] fldGarbageCollectorPointers;
    private final int fldProcessorNumberOfCores;
    private final long fldOperatingSystemAppMinPointer;
    private final long fldOperatingSystemAppMaxPointer;
    private final CriticalSection fldHeapOperation;
    private final String fldOperatingSystemVersion;
    private final Services fldOperatingSystemServices;
    private final OutOfMemoryError fldErrorNotFreedMemory;
    private final InstantiationError fldErrorNotInstancible;
    private final NoClassDefFoundError fldErrorNotDefinedType;

    public () {
        int4 osversion;
        final Package lang = avt.lang.package;
        SystemInfo sysinfo = new SystemInfo();
        Kernel.getSystemInfo(sysinfo.getPointer());
        fldGarbageCollectorIndices = new int[0x0fff];
        fldGarbageCollectorPointers = new long[0x0fff];
        fldProcessorNumberOfCores = sysinfo.dwNumberOfProcessors;
        fldOperatingSystemAppMinPointer = sysinfo.lpMinimumApplicationAddress;
        fldOperatingSystemAppMaxPointer = sysinfo.lpMaximumApplicationAddress;
        fldHeapOperation = new CriticalSection();
        fldOperatingSystemVersion = (new StringBuilder() +
            Int.toUnsignedString((osversion = getOperatingSystemVersion())[0]) + '.' +
            Int.toUnsignedString(osversion[1]) + '.' +
            Int.toUnsignedString(osversion[2])
        ).toString();
        fldOperatingSystemServices = new Services();
        fldErrorNotFreedMemory = new OutOfMemoryError(lang.getResourceString("!machine-error.out-of-memory"));
        fldErrorNotInstancible = new InstantiationError(lang.getResourceString("!reflective-error.instantiation"));
        fldErrorNotDefinedType = new NoClassDefFoundError(lang.getResourceString("!reflective-error.no-class-def-found"));
    }

    public void exit(int exitCode) {
        destruct(securityContext);
        Kernel.exitProcess(exitCode);
    }

    public long freeMemory() {
        long result = 0;
        boolean multiThreaded = this.multiThreaded;
        CriticalSection operation = fldHeapOperation;
        if(multiThreaded) operation.lock();
        try
        {
            for(int index = heapsCatalogue.length; index-- > 0; )
            {
                result += heapsCatalogue[index].freeMemory();
            }
        } finally
        {
            if(multiThreaded) operation.unlock();
        }
        return result;
    }

    public long totalMemory() {
        long result = 0;
        boolean multiThreaded = this.multiThreaded;
        CriticalSection operation = fldHeapOperation;
        if(multiThreaded) operation.lock();
        try
        {
            for(int index = heapsCatalogue.length; index-- > 0; )
            {
                result += heapsCatalogue[index].allocationSize;
            }
        } finally
        {
            if(multiThreaded) operation.unlock();
        }
        return result;
    }

    protected void collectGarbage() {
        for(CriticalSection operation = fldHeapOperation, int topCtlgIdx = 0; topCtlgIdx < heapsCatalogue.length; topCtlgIdx++)
        {
            if(isTerminated()) return;
            Heap64 topHeapRef = heapsCatalogue[topCtlgIdx];
            if(topHeapRef == null) break;
            for(int topHeapIdx = 0; topHeapIdx < topHeapRef.length; topHeapIdx++)
            {
                if(isTerminated()) return;
                long topInstPtr = (long) topHeapRef[topHeapIdx];
                long2 refCounters = refsToInstance(topInstPtr, securityContext);
                label0: if(refCounters == new long2 { 0, 0 } || refCounters == new long2 { 0, refsFromInstance(topInstPtr, topInstPtr, securityContext) })
                {
                    /* Удаляем объект с нулевым количеством ссылок на него или объект, количество ссылок на который равно количеству ссылок из него на него самого */
                    invokeBeforeDestruction(topInstPtr, securityContext);
                    releaseRefsInInstance(topInstPtr, securityContext);
                    operation.lock();
                    try
                    {
                        modCollectedBytes(topHeapRef.free(topInstPtr));
                    } finally
                    {
                        operation.unlock();
                    }
                    topHeapIdx--;
                }
                else if(refCounters[0] == 0)
                {
                    int length = 1;
                    int[] indices = fldGarbageCollectorIndices;
                    long[] pointers = fldGarbageCollectorPointers;
                    indices[0] = topCtlgIdx;
                    pointers[0] = topInstPtr;
                    for(boolean added = true; added; ) for(added = false, int subCtlgIdx = 0; subCtlgIdx < heapsCatalogue.length; subCtlgIdx++)
                    {
                        if(isTerminated()) return;
                        Heap64 subHeapRef = heapsCatalogue[subCtlgIdx];
                        if(subHeapRef == null) break;
                        for(int subHeapIdx = 0; subHeapIdx < subHeapRef.length; subHeapIdx++)
                        {
                            if(isTerminated()) return;
                            long subInstPtr = (long) subHeapRef[subHeapIdx];
                            if(
                                (refCounters = refsToInstance(subInstPtr, securityContext)) == new long2 { 0, 0 } ||
                                refCounters == new long2 { 0, refsFromInstance(subInstPtr, subInstPtr, securityContext) }
                            )
                            {
                                /* Удаляем объект с нулевым количеством ссылок на него или объект, количество ссылок на который равно количеству ссылок из него на него самого */
                                invokeBeforeDestruction(subInstPtr, securityContext);
                                releaseRefsInInstance(subInstPtr, securityContext);
                                operation.lock();
                                try
                                {
                                    modCollectedBytes(subHeapRef.free(subInstPtr));
                                } finally
                                {
                                    operation.unlock();
                                }
                                subHeapIdx--;
                            }
                            else if(refCounters[0] == 0)
                            {
                                for(int pti = length; pti-- > 0; )
                                {
                                    if(isTerminated()) return;
                                    if(refsFromInstance(subInstPtr, pointers[pti], securityContext) > 0)
                                    {
                                        int status = garbageCollectorAddInstance(subCtlgIdx, subInstPtr, indices, pointers, length);
                                        if(status < 0)
                                        {
                                            break label0;
                                        }
                                        if(status > 0)
                                        {
                                            if(status == 1)
                                            {
                                                indices = fldGarbageCollectorIndices;
                                                pointers = fldGarbageCollectorPointers;
                                            }
                                            length++;
                                            added = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                for(int pti = length; pti-- > 0; )
                                {
                                    if(isTerminated()) return;
                                    if(refsFromInstance(subInstPtr, pointers[pti], securityContext) > 0) break label0;
                                }
                            }
                        }
                    }
                    for(int pti = length; pti-- > 0; )
                    {
                        if(isTerminated()) return;
                        long subInstPtr = pointers[pti];
                        if((refCounters = refsToInstance(subInstPtr, securityContext))[0] != 0) break label0;
                        long refCounter = refCounters[1];
                        for(int ptj = length; ptj-- > 0; )
                        {
                            if(isTerminated()) return;
                            refCounter -= refsFromInstance(pointers[ptj], subInstPtr, securityContext);
                        }
                        if(refCounter != 0) break label0;
                    }
                    /* Удаляем «острова изоляции» (группу объектов, которые ссылаются друг на друга и не имеют других ссылок на себя) */
                    for(int pti = 0; pti < length; pti++)
                    {
                        if(isTerminated()) return;
                        invokeBeforeDestruction(pointers[pti], securityContext);
                    }
                    for(int pti = 0; pti < length; pti++)
                    {
                        if(isTerminated()) return;
                        releaseRefsInInstance(pointers[pti], securityContext);
                    }
                    int delta = 0;
                    for(int pti = 0; pti < length; pti++)
                    {
                        if(isTerminated()) return;
                        int subCtlgIdx = indices[pti];
                        long subInstPtr = pointers[pti];
                        Heap64 subHeapRef = heapsCatalogue[subCtlgIdx];
                        if(subCtlgIdx == topCtlgIdx) delta++;
                        operation.lock();
                        try
                        {
                            modCollectedBytes(subHeapRef.free(subInstPtr));
                        } finally
                        {
                            operation.unlock();
                        }
                    }
                    if((topHeapIdx -= delta) < -1) topHeapIdx = -1;
                }
            }
        }
    }

    protected void throwOutOfMemoryError() {
        throw fldErrorNotFreedMemory;
    }

    protected void yieldThread() {
        Kernel.switchToThread();
    }

    protected void startThreadId(long threadId) {
        if(threadId < Int.MIN_VALUE || threadId > Int.MAX_VALUE)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "threadId" }));
        }
        long threadHandle = Kernel.openThread(Kernel.THREAD_SUSPEND_RESUME, false, (int) threadId);
        if(threadHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "threadId" }));
        }
        try
        {
            Kernel.resumeThread(threadHandle);
        } finally
        {
            Kernel.closeHandle(threadHandle);
        }
    }

    protected void setThreadIdPriority(long threadId, int priority) {
        if(threadId < Int.MIN_VALUE || threadId > Int.MAX_VALUE)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "threadId" }));
        }
        long threadHandle = Kernel.openThread(Kernel.THREAD_SET_LIMITED_INFORMATION, false, (int) threadId);
        if(threadHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "threadId" }));
        }
        try
        {
            switch(priority)
            {
            default:
                priority = priority >= Thread.MAX_PRIORITY ? Kernel.THREAD_PRIORITY_TIME_CRITICAL : Kernel.THREAD_PRIORITY_IDLE;
                break;
            case Thread.LOW_PRIORITY - 1:
                priority = Kernel.THREAD_PRIORITY_LOWEST;
                break;
            case Thread.LOW_PRIORITY - 0:
                priority = Kernel.THREAD_PRIORITY_BELOW_NORMAL;
                break;
            case Thread.NORM_PRIORITY - 1:
            case Thread.NORM_PRIORITY + 0:
            case Thread.NORM_PRIORITY + 1:
                priority = Kernel.THREAD_PRIORITY_NORMAL;
                break;
            case Thread.HIGH_PRIORITY + 0:
                priority = Kernel.THREAD_PRIORITY_ABOVE_NORMAL;
                break;
            case Thread.HIGH_PRIORITY + 1:
                priority = Kernel.THREAD_PRIORITY_HIGHEST;
                break;
            }
            Kernel.setThreadPriority(threadHandle, priority);
        } finally
        {
            Kernel.closeHandle(threadHandle);
        }
    }

    protected boolean isAliveThreadId(long threadId) {
        if(threadId < Int.MIN_VALUE || threadId > Int.MAX_VALUE)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "threadId" }));
        }
        long threadHandle = Kernel.openThread(Kernel.THREAD_QUERY_LIMITED_INFORMATION, false, (int) threadId);
        if(threadHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "threadId" }));
        }
        try
        {
            int2 result = Kernel.getExitCodeThread(threadHandle);
            return result[0] != 0 && result[1] == Kernel.STILL_ACTIVE;
        } finally
        {
            Kernel.closeHandle(threadHandle);
        }
    }

    protected boolean isCanonicalPointer(long pointer) {
        return super.isCanonicalPointer(pointer) && pointer >= fldOperatingSystemAppMinPointer && pointer <= fldOperatingSystemAppMaxPointer;
    }

    protected boolean isProtectedMemory(long2 regionPointers) {
        if(super.isProtectedMemory(regionPointers) || isIntersectRegions(toMemoryRegionPointers(heapsCatalogue, heapsAligned), regionPointers)) return true;
        boolean multiThreaded = this.multiThreaded;
        CriticalSection operation = fldHeapOperation;
        if(multiThreaded) operation.lock();
        try
        {
            for(int index = heapsCatalogue.length; index-- > 0; )
            {
                Heap64 heap = heapsCatalogue[index];
                long allocationSize = heap.allocationSize;
                if(
                    isIntersectRegions(toMemoryRegionPointers(heap, getHeapSize(allocationSize)), regionPointers) ||
                    isIntersectRegions(toMemoryRegionPointers(heap.allocationPointer, allocationSize), regionPointers)
                ) return true;
            }
        } finally
        {
            if(multiThreaded) operation.unlock();
        }
        return false;
    }

    protected int getThreadIdPriority(long threadId) {
        if(threadId < Int.MIN_VALUE || threadId > Int.MAX_VALUE)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "threadId" }));
        }
        long threadHandle = Kernel.openThread(Kernel.THREAD_QUERY_LIMITED_INFORMATION, false, (int) threadId);
        if(threadHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "threadId" }));
        }
        try
        {
            switch(Kernel.getThreadPriority(threadHandle))
            {
            case Kernel.THREAD_PRIORITY_IDLE:
                return Thread.MIN_PRIORITY;
            case Kernel.THREAD_PRIORITY_LOWEST:
                return Thread.LOW_PRIORITY - 1;
            case Kernel.THREAD_PRIORITY_BELOW_NORMAL:
                return Thread.LOW_PRIORITY - 0;
            default:
                return Thread.NORM_PRIORITY + 0;
            case Kernel.THREAD_PRIORITY_ABOVE_NORMAL:
                return Thread.HIGH_PRIORITY + 0;
            case Kernel.THREAD_PRIORITY_HIGHEST:
                return Thread.HIGH_PRIORITY + 1;
            case Kernel.THREAD_PRIORITY_TIME_CRITICAL:
                return Thread.MAX_PRIORITY;
            }
        } finally
        {
            Kernel.closeHandle(threadHandle);
        }
    }

    protected int activeThreadsCount() {
        int result = 0;
        int processId = Kernel.getCurrentProcessId();
        long snapshotHandle = Kernel.createToolHelp32Snapshot(Kernel.TH32CS_SNAPTHREAD, 0);
        try
        {
            ThreadEntry32 threadInfoObject = new ThreadEntry32() { dwSize = ThreadEntry32.class.structSize };
            long threadInfoPointer = threadInfoObject.getPointer();
            if(Kernel.thread32First(snapshotHandle, threadInfoPointer)) do
            {
                if(threadInfoObject.th32OwnerProcessID == processId) result++;
            } while(Kernel.thread32Next(snapshotHandle, threadInfoPointer));
        } finally
        {
            Kernel.closeHandle(snapshotHandle);
        }
        return result;
    }

    protected long newThreadId(Thread reference) {
        long result = Kernel.createThread(0, 0x1000L, getThreadEntryPoint(), toPointer(reference), Kernel.CREATE_SUSPENDED)[1];
        addOtherRefInInstance(reference, securityContext);
        return result;
    }

    protected long currentThreadId() {
        return (long) Kernel.getCurrentThreadId();
    }

    protected long[] activeThreadsIds() {
        int length = 0;
        int processId = Kernel.getCurrentProcessId();
        long[] result = new long[0x0fi];
        long snapshotHandle = Kernel.createToolHelp32Snapshot(Kernel.TH32CS_SNAPTHREAD, 0);
        try
        {
            ThreadEntry32 threadInfoObject = new ThreadEntry32() { dwSize = ThreadEntry32.class.structSize };
            long threadInfoPointer = threadInfoObject.getPointer();
            if(Kernel.thread32First(snapshotHandle, threadInfoPointer)) do
            {
                if(threadInfoObject.th32OwnerProcessID == processId)
                {
                    if(length == result.length)
                    {
                        Array.copy(result, 0, result = new long[length << 1 | 1], 0, length);
                    }
                    result[length++] = threadInfoObject.th32ThreadID;
                }
            } while(Kernel.thread32Next(snapshotHandle, threadInfoPointer));
        } finally
        {
            Kernel.closeHandle(snapshotHandle);
        }
        if(length != result.length)
        {
            Array.copy(result, 0, result = new long[length], 0, length);
        }
        return result;
    }

    protected platform.dependent.Event newEvent(long threadId) { return new Win32Event(threadId); }

    protected platform.dependent.Mutex newMutex() { return new CriticalSection(); }

    protected platform.dependent.Monitor newMonitor() { return new Monitor(); }

    protected Object allocateInstance(Class type, long size, int length, boolean executable) {
        if(type == null)
        {
            throw fldErrorNotDefinedType;
        }
        if(type.isPrimitive() || type.isAbstract())
        {
            throw fldErrorNotInstancible;
        }
        int attributes = executable ? EXECUTABLE : NORMAL;
        Object instance = null;
        label0:
        {
            boolean multiThreaded = this.multiThreaded;
            CriticalSection operation = fldHeapOperation;
            if(multiThreaded) operation.lock();
            try
            {
                for(int limit = heapsCatalogue.length, int index = 0; index < limit; index++)
                {
                    Heap64 heap = heapsCatalogue[index];
                    if(heap.attributes != attributes) continue;
                    long pointer = heap.allocateStart(size);
                    if(pointer != 0)
                    {
                        instance = initializeInstance(pointer, type, size + (-size & Heap64.BLOCK_SIZE - 1), length, securityContext);
                        heap.allocateFinish();
                        break label0;
                    }
                }
                Heap64 heap = newHeap(Heap64.getAllocationSize(size), attributes);
                if(heap != null)
                {
                    long pointer = heap.allocateStart(size);
                    if(pointer != 0)
                    {
                        instance = initializeInstance(pointer, type, size + (-size & Heap64.BLOCK_SIZE - 1), length, securityContext);
                        heap.allocateFinish();
                    }
                }
            } finally
            {
                if(multiThreaded) operation.unlock();
            }
        }
        if(instance == null)
        {
            throw fldErrorNotFreedMemory;
        }
        return instance;
    }

    protected int processorNumberOfCores { read = fldProcessorNumberOfCores }

    protected platform.dependent.TimeBase timeBase { read = fldOperatingSystemServices }

    protected FileSystem localFileSystem { read = fldOperatingSystemServices }

    protected String lineSeparator { read = "\r\n" }

    protected String operatingSystemName { read = "Microsoft Windows" }

    protected String operatingSystemVersion { read = fldOperatingSystemVersion }

    protected String entryPointTypeCanonicalName { read = "platform.dependent.mswindows.EntryPoint" }

    protected platform.dependent.ProcessEnvironment currentProcessEnvironment { read = fldOperatingSystemServices }

    private int garbageCollectorAddInstance(int index, long pointer, int[] indices, long[] pointers, int length) {
        if(Array.indexOf(pointer, pointers, 0, length) < 0)
        {
            if(length == pointers.length)
            {
                int capacity = length << 1 | 1;
                if(capacity < 0) return -1;
                Array.copy(pointers, 0, fldGarbageCollectorPointers = pointers = new long[capacity], 0, length);
                Array.copy(indices, 0, fldGarbageCollectorIndices = indices = new int[capacity], 0, length);
                pointers[length] = pointer;
                indices[length] = index;
                return 1;
            }
            pointers[length] = pointer;
            indices[length] = index;
            return 2;
        }
        return 0;
    }
}