示例#1
0
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;
}
示例#2
0
/* 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");
}
示例#3
0
void cPushupButton::SetPushEx(BOOL val)
{
	SetPush(val);
	
	if(cbWindowFunc)
		(*cbWindowFunc)(m_ID, m_pParent, (m_fPushed?WE_PUSHDOWN:WE_PUSHUP));
}
示例#4
0
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;
}
示例#5
0
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);
}
示例#6
0
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));

}