mem_t AllocBigArray_GenConc(Proc_t *proc, Thread_t *thread, ArraySpec_t *spec) { mem_t region; ptr_t obj = NULL; /* Double length for PointerField to make MirrorPtrArray */ int specByteLen = spec->byteLen; int i, segments = (specByteLen <= arraySegmentSize) ? 0 : DivideUp(specByteLen, arraySegmentSize); int tagByteLen = specByteLen + 4 + 4 * segments; Align_t align = (spec->type == DoubleField) ? ((segments & 1) ? EvenWordAlign : OddWordAlign) : NoWordAlign; /* Allocate the space */ assert(spec->type != PointerField); if (spec->type == MirrorPointerField) { region = AllocFromHeap(fromSpace, thread, tagByteLen, align); if (region == NULL) { GCFromC(thread, tagByteLen + 4, 1); region = AllocFromHeap(fromSpace, thread, tagByteLen, align); } } else { region = gc_large_alloc(proc, tagByteLen, align); if (region == NULL) { GCFromC(thread, 4, 1); /* not bytelen since object is not from tenured space */ region = gc_large_alloc(proc, tagByteLen, align); } } /* Should do work proportional to size of array */ /* if (GCStatus != GCOff && GCStatus != GCPendingOn && GCStatus != GCPendingAgressive) do_work(proc, CollectionRate * tagByteLen); */ assert(region != NULL); proc->segUsage.bytesAllocated += tagByteLen; /* Allocate object; update stats; initialize */ obj = region + 1 + segments; for (i=0; i<segments; i++) obj[-(2+i)] = SEGPROCEED_TAG; switch (spec->type) { case IntField : init_iarray(obj, spec->elemLen, spec->intVal); break; case PointerField : DIE("pointer array"); case MirrorPointerField : init_double_ptr_array(obj, spec->elemLen, spec->pointerVal); SetPush(&proc->work.backObjs, obj); SetPush(&proc->work.nextBackObjs, obj); break; case DoubleField : init_farray(obj, spec->elemLen, spec->doubleVal); break; } return obj; }
/* maxOffset is non-zero if the caller passed arguments on the stack */ void NewStackletFromMutator(Thread_t* curThread, int maxOffset) { int i; mem_t sp = (mem_t) curThread->saveregs[SP]; mem_t returnToCaller = (mem_t) curThread->saveregs[ASMTMP2]; volatile reg_t* primaryRegs; mem_t returnToCallee = (mem_t) curThread->saveregs[RA]; Stacklet_t *oldStacklet, *newStacklet; StackChain_t *stackChain = (StackChain_t *) curThread->stack; oldStacklet = EstablishStacklet(stackChain, sp); /* saves sp already */ oldStacklet->retadd = returnToCaller; primaryRegs = &oldStacklet->bottomBaseRegs[primaryStackletOffset == 0 ? 0 : 32]; for (i=0; i<32; i++) { primaryRegs[i] = curThread->saveregs[i]; if ((1<<i) & calleeSaveMask) curThread->saveregs[i] = 0; } if (addOldStackletOnUnderflow && GCStatus != GCOff && oldStacklet->state == Inconsistent) { oldStacklet->state = Pending; SetPush(&curThread->proc->work.stacklets, (ptr_t) oldStacklet); } assert(maxOffset == 0); /* Not handling overflow arguments yet */ newStacklet = NewStacklet(stackChain); curThread->saveregs[SP] = (val_t) StackletPrimaryCursor(newStacklet); curThread->stackLimit = StackletPrimaryBottom(newStacklet); curThread->stackTop = StackletPrimaryTop(newStacklet); curThread->saveregs[RA] = mkra((void*)&PopStackletFromML); Stacklet_KillReplica(newStacklet); returnToML(curThread, returnToCallee); DIE("mutator returned"); }
void cPushupButton::SetPushEx(BOOL val) { SetPush(val); if(cbWindowFunc) (*cbWindowFunc)(m_ID, m_pParent, (m_fPushed?WE_PUSHDOWN:WE_PUSHUP)); }
DWORD cPushupButton::ActionEvent(CMouse * mouseInfo) { if( !m_bActive ) return WE_NULL; DWORD we = cWindow::ActionEvent(mouseInfo); if( m_bDisable ) return we; long x2 = mouseInfo->GetMouseEventX(); long y2 = mouseInfo->GetMouseEventY(); if(m_fPassive) { if( we & ( WE_LBTNCLICK | WE_LBTNDBLCLICK ) ) { if(PtInWindow(x2, y2)) { (m_fPushed?we |= WE_PUSHUP:we |= WE_PUSHDOWN); cbWindowFunc(m_ID, m_pParent, (m_fPushed?WE_PUSHUP:WE_PUSHDOWN)); } } } else { if( we & ( WE_LBTNCLICK | WE_LBTNDBLCLICK ) ) { if(PtInWindow(x2, y2)) { m_fPushed ^= TRUE; SetPush(m_fPushed); if(cbWindowFunc) { (m_fPushed?we |= WE_PUSHDOWN:we |= WE_PUSHUP); (*cbWindowFunc)(m_ID, m_pParent, (m_fPushed?WE_PUSHDOWN:WE_PUSHUP)); } } } } return we; }
void GCRelease_GenConc(Proc_t *proc) { mem_t allocCurrent = proc->allocStart; mem_t allocStop = proc->allocCursor; ploc_t writelistCurrent = proc->writelistStart; ploc_t writelistStop = proc->writelistCursor; int isGCAgressive = (GCType == Major ? doAgressive : doMinorAgressive) ? (GCStatus == GCAgressive) || (GCStatus == GCPendingOn) : 0; int isGCOn = isGCAgressive || (GCStatus == GCOn) || (GCStatus == GCPendingOff); Heap_t *srcRange = (GCType == Minor) ? nursery : fromSpace; int numWrites = (proc->writelistCursor - proc->writelistStart) / 3; /* Reset cursors */ proc->allocStart = proc->allocCursor; proc->writelistCursor = proc->writelistStart; /* Replicate objects allocated by mutator when the collector is on */ if (isGCOn && !isGCAgressive) { procChangeState(proc, GCReplicate, 613); if (collectDiag >= 2) printf("GC %4d/%6d: Double-allocating %lx to %lx\n", NumGC, proc->segmentNumber, (long)allocCurrent,(long)allocStop); proc->segUsage.bytesReplicated += sizeof(val_t) * (allocStop - allocCurrent); while (allocCurrent + 1 <= allocStop) { /* There may be no data for empty array */ int objSize; ptr_t obj = allocCurrent; /* Eventually becomes start of object */ tag_t tag = *obj; if (IS_SKIP_TAG(tag)) { allocCurrent += GET_SKIPWORD(tag); continue; } while (tag == SEGPROCEED_TAG || tag == SEGSTALL_TAG) tag = *(++obj); /* Skip past segment tags */ obj++; /* Skip past object tag */ alloc_copyCopySync_primarySet(proc,obj); objSize = proc->bytesCopied; if (objSize == 0) { mem_t dummy = NULL; objSize = objectLength(obj, &dummy); fastAssert(dummy == allocCurrent); } allocCurrent += objSize / sizeof(val_t); } } /* Process writes */ if (collectDiag >= 2 && writelistCurrent < writelistStop) printf("Proc %d: Processing %d writes from %lx to %lx\n", proc->procid,numWrites,(long)writelistCurrent,(long)writelistStop); procChangeState(proc, GCWrite, 614); while (writelistCurrent < writelistStop) { ptr_t mutatorPrimary = *writelistCurrent++; /* Global, nursery, or fromSpace */ int byteDisp = (int) *writelistCurrent++; ptr_t possPrevPtrVal = (ptr_t) *writelistCurrent++; /* Pointer value only if pointer array was modified */ int wordDisp = byteDisp / sizeof(val_t); int mirrorWordDisp = (primaryArrayOffset == 0) ? wordDisp + 1 : wordDisp - 1; int doubleWordDisp = byteDisp / (sizeof(double)); int byteLen; /* Length of data portion of array */ int syncIndex; if (IsGlobalData(mutatorPrimary)) { add_global_root(proc,mutatorPrimary); continue; } if (inHeap(mutatorPrimary, largeSpace)) continue; if (!isGCOn) { /* Record back-pointers when GC is off for roots of next GC */ if (GCType == Minor && /* If next GC is major, no backLocs needed */ inHeap(mutatorPrimary, fromSpace)) { tag_t tag = mutatorPrimary[-1]; if (GET_TYPE(tag) == MIRROR_PTR_ARRAY_TYPE) { SetPush(&proc->work.backLocs, (ptr_t) &mutatorPrimary[wordDisp]); SetPush(&proc->work.nextBackLocs, (ptr_t) &mutatorPrimary[mirrorWordDisp]); } else fastAssert((GET_TYPE(tag) == WORD_ARRAY_TYPE || GET_TYPE(tag) == QUAD_ARRAY_TYPE)); } } else { vptr_t nurseryPrimary = NULL; /* Used if primary was in nursery */ vptr_t fromSpaceEither = NULL; /* Used for primaryReplica or (minor replica/major primary) */ vptr_t toSpaceReplica = NULL; /* Used only during major GC*/ tag_t tag; /* Actual tag deteremined after traversing forwarding pointers */ /* Make a copy of the modified arrays and get tag */ if (inHeap(mutatorPrimary, nursery)) { fastAssert(GCType == Minor); nurseryPrimary = mutatorPrimary; tag = nurseryPrimary[-1]; /* If object has not been copied, simply gray previous pointer value */ switch (GET_TYPE(tag)) { case PTR_ARRAY_TYPE: case MIRROR_PTR_ARRAY_TYPE: alloc1_copyCopySync_primarySet(proc,possPrevPtrVal, srcRange); continue; case WORD_ARRAY_TYPE: case QUAD_ARRAY_TYPE: continue; } while ((val_t)(fromSpaceEither = (ptr_t) nurseryPrimary[-1]) == STALL_TAG) ; tag = fromSpaceEither[-1]; } else if (inHeap(mutatorPrimary,fromSpace)) { fromSpaceEither = mutatorPrimary; if (GCType == Major) { alloc1_copyCopySync_primarySet(proc,(ptr_t) fromSpaceEither,srcRange); toSpaceReplica = (ptr_t) fromSpaceEither[-1]; tag = toSpaceReplica[-1]; } else tag = fromSpaceEither[-1]; } else DIE("mutatorPrimary in neither fromSpace nor nursery"); /* Copy-Write synchronization on replica object */ byteLen = GET_ANY_ARRAY_LEN(tag); syncIndex = (byteLen <= arraySegmentSize) ? -1 : -2-(DivideDown(byteDisp, arraySegmentSize)); if (nurseryPrimary) while (fromSpaceEither[syncIndex] == SEGSTALL_TAG) ; else if (toSpaceReplica) while (toSpaceReplica[syncIndex] == SEGSTALL_TAG) ; switch (GET_TYPE(tag)) { case WORD_ARRAY_TYPE: if (nurseryPrimary) { if (fromSpaceEither[0] == (val_t) nurseryPrimary) /* Backpointer present indicates object not yet scanned - can/must skip replica update */ break; fromSpaceEither[wordDisp] = nurseryPrimary[wordDisp]; } if (toSpaceReplica) toSpaceReplica[wordDisp] = fromSpaceEither[wordDisp]; break; case QUAD_ARRAY_TYPE: if (nurseryPrimary) { if (fromSpaceEither[0] == (val_t) nurseryPrimary) /* Backpointer present indicates object not yet scanned - can/must skip replica update */ break; ((double *)fromSpaceEither)[doubleWordDisp] = ((double *)nurseryPrimary)[doubleWordDisp]; } if (toSpaceReplica) ((double *)toSpaceReplica)[doubleWordDisp] = ((double *)fromSpaceEither)[doubleWordDisp]; break; case PTR_ARRAY_TYPE: DIE("pointer array"); case MIRROR_PTR_ARRAY_TYPE: { /* Snapshot-at-the-beginning (Yuasa) write barrier requires copying prevPtrVal even if it might die to prevent the mutator from hiding live data. There are several cases: (1) MinorGC: The original array is in nursery/fromSpace. (i) (a) The field is in nursery. Update new/existing array (replica entry) with new (fromSpace) field. (b) The field is in fromSpace. Update new/existing array (replica entry) with same field. (c) The field is in global/largeSpace. Update new/existing array (replica entry) with same field. (ii) If original array in fromSpace, add location to backLocs for replication. Same as when GC is off. (3) MajorGC: The original array must be in fromSpace. (a) The field is in fromSpace. Update new array (replica entry) with new (toSpace) field. (b) The field is in global/largeSpace. Update new array with field. (toSpaceField is NULL). */ ptr_t mutatorField = (ptr_t) mutatorPrimary[wordDisp]; fastAssert(((byteDisp - primaryArrayOffset) % (2 * sizeof(val_t))) == 0); /* Snapshot-at-the-beginning (Yuasa) write barrier requires copying prevPtrVal even if it might die to prevent the mutator from hiding live data */ alloc1_copyCopySync_primarySet(proc,possPrevPtrVal,srcRange); if (GCType == Minor) { ptr_t newField = mutatorField; if (inHeap(newField, nursery)) { alloc1_copyCopySync_primarySet(proc,mutatorField,srcRange); newField = (ptr_t) mutatorField[-1]; } fastAssert(!inHeap(newField, nursery)); if (fromSpaceEither[0] == (val_t) mutatorPrimary) /* Backpointer present indicates object not yet scanned - can/must skip replica update */ break; fromSpaceEither[mirrorWordDisp] = (val_t) newField; if (inHeap(mutatorPrimary, nursery)) fromSpaceEither[wordDisp] = (val_t) newField; else { fastAssert(inHeap(mutatorPrimary, fromSpace)); SetPush(&proc->work.backLocs, (ptr_t) &mutatorPrimary[wordDisp]); SetPush(&proc->work.nextBackLocs, (ptr_t) &mutatorPrimary[mirrorWordDisp]); } } else { /* GCType == Major */ ptr_t newField = mutatorField; fastAssert(inHeap(mutatorPrimary,fromSpace)); if (inHeap(newField,fromSpace)) { alloc1L_copyCopySync_primarySet(proc,mutatorField,srcRange,largeSpace); newField = (ptr_t) mutatorField[-1]; } if (toSpaceReplica[0] == (val_t) mutatorPrimary) /* Backpointer present indicates object not yet scanned - can/must skip replica update */ break; toSpaceReplica[wordDisp] = (val_t) newField; toSpaceReplica[mirrorWordDisp] = (val_t) newField; } break; } default: DIE("bad tag type"); } /* else */ } /* switch */ } /* while */ if (isGCOn) pushSharedStack(1,workStack, &proc->work); }
static void do_work(Proc_t *proc, int additionalWork) { Heap_t *srcRange = (GCType == Minor) ? nursery : fromSpace; if (additionalWork <= 0) return; addMaxWork(proc, additionalWork); procChangeState(proc, GCWork, 612); proc->segmentType |= (GCType == Major) ? MajorWork : MinorWork; if (collectDiag >= 2) printf("GC %4d/%6d: Entered do_work(%d) updateWorkDone = %5d\n", NumGC, proc->segmentNumber, additionalWork, updateGetWorkDone(proc)); while (!reachMaxWork(proc)) { ploc_t rootLoc, globalLoc, backLoc; ptr_t backObj, gray; int largeStart, largeEnd; Stacklet_t *stacklet; /* Get shared work */ popSharedStack(workStack, &proc->work); if ((GCStatus == GCPendingOn || GCStatus == GCPendingOff) && isLocalWorkEmpty(&proc->work)) break; /* Do the thread stacklets - we can afford to call updateWorkDone often */ while (!reachCheckWork(proc) && ((stacklet = (Stacklet_t *) SetPop(&proc->work.stacklets)) != NULL)) { if (!work_root_scan(proc, stacklet)) SetPush(&proc->work.stacklets, (ptr_t) stacklet); } /* Do the rootLocs */ if (GCType == Minor) { while (!reachCheckWork(proc) && ((rootLoc = (ploc_t) SetPop(&proc->work.roots)) != NULL)) { locAlloc1_copyCopySync_primarySet(proc,rootLoc,srcRange); proc->segUsage.fieldsScanned++; } } else { while (!reachCheckWork(proc) && ((rootLoc = (ploc_t) SetPop(&proc->work.roots)) != NULL)) { locAlloc1L_copyCopySync_primarySet(proc,rootLoc,srcRange,largeSpace); proc->segUsage.fieldsScanned++; } } /* Do the backObjs and backLocs */ if (GCType == Minor) { while (!updateReachCheckWork(proc) && ((backObj = (ptr_t) SetPop(&proc->work.backObjs)) != NULL)) { selfTransferScanObj_locAlloc1_copyCopySync_primarySet(proc,backObj,srcRange); } while (!reachCheckWork(proc) && ((backLoc = (ploc_t) SetPop(&proc->work.backLocs)) != NULL)) { ploc_t mirrorBackLoc = backLoc + ((primaryArrayOffset == 0) ? 1 : -1); *mirrorBackLoc = *backLoc; locAlloc1_copyCopySync_primarySet(proc,mirrorBackLoc,srcRange); proc->segUsage.fieldsScanned += 2; } } else { SetReset(&proc->work.backObjs); SetReset(&proc->work.backLocs); } /* Do the globalLocs */ if (GCType == Minor) while (!reachCheckWork(proc) && ((globalLoc = (ploc_t) SetPop(&proc->work.globals)) != NULL)) { ploc_t replicaLoc = (ploc_t) DupGlobal((ptr_t) globalLoc); locAlloc1_copyCopySync_primarySet(proc,replicaLoc,srcRange); proc->segUsage.globalsProcessed++; } else while (!reachCheckWork(proc) && ((globalLoc = (ploc_t) SetPop(&proc->work.globals)) != NULL)) { ploc_t replicaLoc = (ploc_t) DupGlobal((ptr_t) globalLoc); locAlloc1L_copyCopySync_primarySet(proc,replicaLoc,srcRange,largeSpace); proc->segUsage.globalsProcessed++; } /* Do the large objects - don't need to optimize loop */ while (!updateReachCheckWork(proc) && (gray = SetPop3(&proc->work.segments,(ptr_t *)&largeStart,(ptr_t *)&largeEnd))) { if (GCType == Minor) { int isMirrorPtrArray = (GET_TYPE(gray[-1]) == MIRROR_PTR_ARRAY_TYPE); if (isMirrorPtrArray) { fastAssert(inHeap(gray, fromSpace)); selfTransferScanSegment_copyWriteSync_locAlloc1_copyCopySync_primarySet(proc,gray,largeStart,largeEnd,srcRange); } else transferScanSegment_copyWriteSync_locAlloc1_copyCopySync_primarySet(proc,gray,largeStart,largeEnd,srcRange); } else transferScanSegment_copyWriteSync_locAlloc1L_copyCopySync_primarySet(proc,gray,largeStart,largeEnd,srcRange, largeSpace); } /* Work on the gray objects */ if (GCType == Minor) while (!reachCheckWork(proc) && ((gray = SetPop(&proc->work.objs)) != NULL)) transferScanObj_copyWriteSync_locAlloc1_copyCopySync_primarySet(proc,gray,srcRange); else while (!reachCheckWork(proc) && ((gray = SetPop(&proc->work.objs)) != NULL)) transferScanObj_copyWriteSync_locAlloc1L_copyCopySync_primarySet(proc,gray,srcRange,largeSpace); /* Put work back on shared stack */ if (pushSharedStack(0,workStack,&proc->work)) { if (GCStatus == GCAgressive) GCStatus = GCPendingOn; else if (GCStatus == GCOn) GCStatus = GCPendingOff; } } assert(isLocalWorkEmpty(&proc->work)); if (collectDiag >= 2) printf("GC %d Seg %d: Completed do_work(%d) segWork = %5d sharedStack(%4ld items %2ld segs) %ld alloc %ld copied\n", NumGC, proc->segmentNumber, additionalWork, updateGetWorkDone(proc), SetLength(&workStack->work.objs), SetLength(&workStack->work.segments), proc->cycleUsage.bytesAllocated + proc->segUsage.bytesAllocated, bytesCopied(&proc->cycleUsage) + bytesCopied(&proc->segUsage)); }