示例#1
0
PointersOTE* __fastcall ObjectMemory::shallowCopy(PointersOTE* ote)
{
	ASSERT(!ote->isBytes());

	// A pointer object is a bit more tricky to copy (but not much)
	VariantObject* obj = ote->m_location;
	BehaviorOTE* classPointer = ote->m_oteClass;

	PointersOTE* copyPointer;
	MWORD size;

	if (ote->heapSpace() == OTEFlags::VirtualSpace)
	{
		Interpreter::resizeActiveProcess();

		//size = obj->PointerSize();
		size = ote->pointersSize();

		VirtualObject* pVObj = reinterpret_cast<VirtualObject*>(obj);
		VirtualObjectHeader* pBase = pVObj->getHeader();
		unsigned maxByteSize = pBase->getMaxAllocation();
		unsigned currentTotalByteSize = pBase->getCurrentAllocation();

		VirtualOTE* virtualCopy = ObjectMemory::newVirtualObject(classPointer,
			currentTotalByteSize / sizeof(MWORD),
			maxByteSize / sizeof(MWORD));
		if (!virtualCopy)
			return nullptr;

		pVObj = virtualCopy->m_location;
		pBase = pVObj->getHeader();
		ASSERT(pBase->getMaxAllocation() == maxByteSize);
		ASSERT(pBase->getCurrentAllocation() == currentTotalByteSize);
		virtualCopy->setSize(ote->getSize());

		copyPointer = reinterpret_cast<PointersOTE*>(virtualCopy);
	}
	else
	{
		//size = obj->PointerSize();
		size = ote->pointersSize();
		copyPointer = newPointerObject(classPointer, size);
	}

	// Now copy over all the fields
	VariantObject* copy = copyPointer->m_location;
	ASSERT(copyPointer->pointersSize() == size);
	for (unsigned i = 0; i<size; i++)
	{
		copy->m_fields[i] = obj->m_fields[i];
		countUp(obj->m_fields[i]);
	}
	return copyPointer;
}
示例#2
0
// Resize an object in VirtualSpace (commit/decommit some memory)
// N.B. Assumes that there are no ref. counted object above shrinkTo (primarily intended for
// Process stacks)
POBJECT ObjectMemory::resizeVirtual(OTE* ote, MWORD newByteSize)
{
	ASSERT(ote->heapSpace() == OTEFlags::VirtualSpace);

	VariantObject* pObject = static_cast<VariantObject*>(ote->m_location);
	VirtualObject* pVObj = reinterpret_cast<VirtualObject*>(pObject);
	VirtualObjectHeader* pBase = pVObj->getHeader();
	unsigned maxByteSize = pBase->getMaxAllocation(); maxByteSize;
	unsigned currentTotalByteSize = pBase->getCurrentAllocation();
	ASSERT(_ROUND2(currentTotalByteSize, dwPageSize) == currentTotalByteSize);
	unsigned newTotalByteSize = _ROUND2(newByteSize + sizeof(VirtualObjectHeader), dwPageSize);
	// Minimum virtual allocation is one page (4k normally)
	ASSERT(newTotalByteSize >= dwPageSize);
	
	if (newTotalByteSize > currentTotalByteSize)
	{
		// The object is increasing in size - commit some more memory
		ASSERT(newByteSize <= maxByteSize);
		unsigned allocSize = newTotalByteSize - currentTotalByteSize;
		ASSERT(_ROUND2(allocSize, dwPageSize) == allocSize);
		if (!::VirtualAlloc(reinterpret_cast<BYTE*>(pBase) + currentTotalByteSize, allocSize, MEM_COMMIT, PAGE_READWRITE))
			return 0;	// Request to resize failed
	}
	else if (newTotalByteSize < currentTotalByteSize)
	{
		const Behavior* behavior = ote->m_oteClass->m_location; behavior;
		// The object is shrinking - decommit some memory
		ASSERT(newByteSize > (ObjectHeaderSize+behavior->fixedFields())*sizeof(MWORD));

		MWORD* pCeiling = reinterpret_cast<MWORD*>(reinterpret_cast<BYTE*>(pBase) + newTotalByteSize);

		// Determine the size of the committed region above shrinkTo
		MEMORY_BASIC_INFORMATION mbi;
		VERIFY(::VirtualQuery(pCeiling, &mbi, sizeof(mbi)) == sizeof(mbi));
		ASSERT(mbi.AllocationBase == pBase);
		if (mbi.State == MEM_COMMIT)
		{
			// Decommit memory above new ceiling
			VERIFY(::VirtualFree(pCeiling, mbi.RegionSize, MEM_DECOMMIT));
		}
	}
	
	// And resize the object as far as Smalltalk is concerned to the nearest page boundary
	// above and including shrinkTo
	//pBase->setCurrentAllocation(newTotalByteSize);
	ote->setSize(newByteSize);

	return pObject;
}