@Inline private boolean acquireRecyclableBlockAddressOrder() { if (recyclableExhausted) { if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { Log.writeln("[no recyclable available]"); } return false; } int markState = 0; boolean usable = false; while (!usable) { Address next = recyclableBlock.plus(BYTES_IN_BLOCK); if (recyclableBlock.isZero() || ImmixSpace.isRecycleAllocChunkAligned(next)) { recyclableBlock = space.acquireReusableBlocks(); if (recyclableBlock.isZero()) { recyclableExhausted = true; if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { Log.writeln("[recyclable exhausted]"); } line = LINES_IN_BLOCK; return false; } } else { recyclableBlock = next; } markState = Block.getBlockMarkState(recyclableBlock); usable = (markState > 0 && markState <= ImmixSpace.getReusuableMarkStateThreshold(copy)); if (copy && Block.isDefragSource(recyclableBlock)) usable = false; } if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(recyclableBlock)); Block.setBlockAsReused(recyclableBlock); lineUseCount += (LINES_IN_BLOCK - markState); return true; // found something good }
/** * Takes the passed address and (atomically) performs any read barrier actions before returning it * as an object. * * @param tmp The non-zero referent address * @return The referent object. */ @Uninterruptible @Inline Object getInternal() { if (RVMType.JavaLangRefReferenceReferenceField.madeTraced()) { if (NEEDS_OBJECT_GETFIELD_BARRIER) { return Barriers.objectFieldRead( this, RVMType.JavaLangRefReferenceReferenceField.getOffset(), RVMType.JavaLangRefReferenceReferenceField.getId()); } else { return Magic.getObjectAtOffset( this, RVMType.JavaLangRefReferenceReferenceField.getOffset(), RVMType.JavaLangRefReferenceReferenceField.getId()); } } else { Address tmp = _referent; if (tmp.isZero()) { return null; } else { Object ref = Magic.addressAsObject(tmp); if (Barriers.NEEDS_JAVA_LANG_REFERENCE_READ_BARRIER) { ref = Barriers.javaLangReferenceReadBarrier(ref); } return ref; } } }
/** * Push an address onto the address stack. * * @param object the object to be pushed onto the object queue */ @Inline public final void push(ObjectReference object) { Address addr = object.toAddress(); if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr.isZero()); checkHeadInsert(1); uncheckedHeadInsert(addr); }
/** Called after we've successfully loaded the shared library */ private void callOnLoad() { // Run any JNI_OnLoad functions defined within the library Address JNI_OnLoadAddress = getSymbol("JNI_OnLoad"); if (!JNI_OnLoadAddress.isZero()) { int version = runJNI_OnLoad(JNI_OnLoadAddress); checkJNIVersion(version); } }
/** Sweep through the large pages, releasing all superpages on the "from space" treadmill. */ private void sweepLargePages(boolean sweepNursery) { while (true) { Address cell = sweepNursery ? treadmill.popNursery() : treadmill.pop(); if (cell.isZero()) break; release(getSuperPage(cell)); } if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(sweepNursery ? treadmill.nurseryEmpty() : treadmill.fromSpaceEmpty()); }
/** * Resolve a symbol to an address in a currently loaded dynamic library. * * @return the address of the symbol of Address.zero() if it cannot be resolved */ public static synchronized Address resolveSymbol(String symbol) { for (VM_DynamicLibrary lib : dynamicLibraries.values()) { Address symbolAddress = lib.getSymbol(symbol); if (!symbolAddress.isZero()) { return symbolAddress; } } return Address.zero(); }
/** * Load a dynamic library and maintain it in this object. * * @param libraryName library name */ private VM_DynamicLibrary(String libraryName) { // Convert file name from unicode to filesystem character set. // (Assume file name is ASCII, for now). // byte[] asciiName = VM_StringUtilities.stringToBytesNullTerminated(libraryName); // make sure we have enough stack to load the library. // This operation has been known to require more than 20K of stack. VM_Thread myThread = VM_Scheduler.getCurrentThread(); Offset remaining = VM_Magic.getFramePointer().diff(myThread.stackLimit); int stackNeededInBytes = VM_StackframeLayoutConstants.STACK_SIZE_DLOPEN - remaining.toInt(); if (stackNeededInBytes > 0) { if (myThread.hasNativeStackFrame()) { throw new java.lang.StackOverflowError("dlopen"); } else { VM_Thread.resizeCurrentStack(myThread.getStackLength() + stackNeededInBytes, null); } } libHandler = VM_SysCall.sysCall.sysDlopen(asciiName); if (libHandler.isZero()) { VM.sysWriteln("error loading library: " + libraryName); throw new UnsatisfiedLinkError(); } libName = libraryName; try { callOnLoad(); } catch (UnsatisfiedLinkError e) { unload(); throw e; } if (VM.verboseJNI) { VM.sysWriteln("[Loaded native library: " + libName + "]"); } }
/** * External allocation slow path (called by superclass when slow path is actually taken. This is * necessary (rather than a direct call from the fast path) because of the possibility of a thread * switch and corresponding re-association of bump pointers to kernel threads. * * @param bytes The number of bytes allocated * @param align The requested alignment * @param offset The offset from the alignment * @return The address of the first byte of the allocated region or zero on failure */ protected final Address allocSlowOnce(int bytes, int align, int offset) { Address ptr = space.getSpace(hot, copy, lineUseCount); if (ptr.isZero()) { lineUseCount = 0; return ptr; // failed allocation --- we will need to GC } /* we have been given a clean block */ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isAligned(ptr)); lineUseCount = LINES_IN_BLOCK; zeroBlock(ptr); if (requestForLarge) { largeCursor = ptr; largeLimit = ptr.plus(BYTES_IN_BLOCK); } else { cursor = ptr; limit = ptr.plus(BYTES_IN_BLOCK); } return alloc(bytes, align, offset); }
/** * Push an address onto the address stack. * * @param addr the address to be pushed onto the address queue */ @Inline public final void push(Address addr) { if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr.isZero()); checkHeadInsert(1); uncheckedHeadInsert(addr); }
@Uninterruptible public static boolean validRef(ObjectReference ref) { if (ref.isNull()) return true; if (!Space.isMappedObject(ref)) { VM.sysWrite("validRef: REF outside heap, ref = "); VM.sysWrite(ref); VM.sysWrite("\n"); Space.printVMMap(); return false; } if (MOVES_OBJECTS) { /* TODO: Work out how to check if forwarded if (Plan.isForwardedOrBeingForwarded(ref)) { // TODO: actually follow forwarding pointer // (need to bound recursion when things are broken!!) return true; } */ } TIB tib = ObjectModel.getTIB(ref); Address tibAddr = Magic.objectAsAddress(tib); if (!Space.isMappedObject(ObjectReference.fromObject(tib))) { VM.sysWrite("validRef: TIB outside heap, ref = "); VM.sysWrite(ref); VM.sysWrite(" tib = "); VM.sysWrite(tibAddr); VM.sysWrite("\n"); ObjectModel.dumpHeader(ref); return false; } if (tibAddr.isZero()) { VM.sysWrite("validRef: TIB is Zero! "); VM.sysWrite(ref); VM.sysWrite("\n"); ObjectModel.dumpHeader(ref); return false; } if (tib.length() == 0) { VM.sysWrite("validRef: TIB length zero, ref = "); VM.sysWrite(ref); VM.sysWrite(" tib = "); VM.sysWrite(tibAddr); VM.sysWrite("\n"); ObjectModel.dumpHeader(ref); return false; } ObjectReference type = ObjectReference.fromObject(tib.getType()); if (!validType(type)) { VM.sysWrite("validRef: invalid TYPE, ref = "); VM.sysWrite(ref); VM.sysWrite(" tib = "); VM.sysWrite(Magic.objectAsAddress(tib)); VM.sysWrite(" type = "); VM.sysWrite(type); VM.sysWrite("\n"); ObjectModel.dumpHeader(ref); return false; } return true; } // validRef