예제 #1
0
OTE* ObjectMemory::CopyElements(OTE* oteObj, MWORD startingAt, MWORD count)
{
	// Note that startingAt is expected to be a zero-based index
	ASSERT(startingAt >= 0);
	OTE* oteSlice;

	if (oteObj->isBytes())
	{
		BytesOTE* oteBytes = reinterpret_cast<BytesOTE*>(oteObj);
		size_t elementSize = ObjectMemory::GetBytesElementSize(oteBytes);

		if (count == 0 || ((startingAt + count) * elementSize <= oteBytes->bytesSize()))
		{
			MWORD objectSize = elementSize * count;

			if (oteBytes->m_flags.m_weakOrZ)
			{
				// TODO: Allocate the correct number of null term bytes based on the encoding
				auto newBytes = static_cast<VariantByteObject*>(allocObject(objectSize + NULLTERMSIZE, oteSlice));
				// When copying strings, the slices has the same string class
				(oteSlice->m_oteClass = oteBytes->m_oteClass)->countUp();
				memcpy(newBytes->m_fields, oteBytes->m_location->m_fields + (startingAt * elementSize), objectSize);
				*reinterpret_cast<NULLTERMTYPE*>(&newBytes->m_fields[objectSize]) = 0;
				oteSlice->beNullTerminated();
				return oteSlice;
			}
			else
			{
				VariantByteObject* newBytes = static_cast<VariantByteObject*>(allocObject(objectSize, oteSlice));
				// When copying bytes, the slice is always a ByteArray
				oteSlice->m_oteClass = Pointers.ClassByteArray;
				oteSlice->beBytes();
				memcpy(newBytes->m_fields, oteBytes->m_location->m_fields + (startingAt * elementSize), objectSize);
				return oteSlice;
			}
		}
	}
	else
	{
		// Pointers
		PointersOTE* otePointers = reinterpret_cast<PointersOTE*>(oteObj);
		BehaviorOTE* oteClass = otePointers->m_oteClass;
		InstanceSpecification instSpec = oteClass->m_location->m_instanceSpec;
		if (instSpec.m_indexable)
		{
			startingAt += instSpec.m_fixedFields;

			if (count == 0 || (startingAt + count) <= otePointers->pointersSize())
			{
				MWORD objectSize = SizeOfPointers(count);
				auto pSlice = static_cast<VariantObject*>(allocObject(objectSize, oteSlice));
				// When copying pointers, the slice is always an Array
				oteSlice->m_oteClass = Pointers.ClassArray;
				VariantObject* pSrc = otePointers->m_location;
				for (MWORD i = 0; i < count; i++)
				{
					countUp(pSlice->m_fields[i] = pSrc->m_fields[startingAt + i]);
				}
				return oteSlice;
			}
		}
	}

	return nullptr;
}
예제 #2
0
template <bool MaybeZ, bool Initialized> BytesOTE* ObjectMemory::newByteObject(BehaviorOTE* classPointer, MWORD elementCount)
{
	Behavior& byteClass = *classPointer->m_location;
	OTE* ote;

	if (!MaybeZ || !byteClass.m_instanceSpec.m_nullTerminated)
	{
		ASSERT(!classPointer->m_location->m_instanceSpec.m_nullTerminated);

		VariantByteObject* newBytes = static_cast<VariantByteObject*>(allocObject(elementCount + SizeOfPointers(0), ote));
		ASSERT((elementCount > MaxSizeOfPoolObject && ote->heapSpace() == OTEFlags::NormalSpace)
			|| ote->heapSpace() == OTEFlags::PoolSpace);

		ASSERT(ote->getSize() == elementCount + SizeOfPointers(0));

		if (Initialized)
		{
			// Byte objects are initialized to zeros (but not the header)
			// Note that we round up to initialize to the next DWORD
			// This can be useful when working on a 32-bit word machine
			ZeroMemory(newBytes->m_fields, _ROUND2(elementCount, sizeof(DWORD)));
			classPointer->countUp();
		}

		ote->m_oteClass = classPointer;
		ote->beBytes();
	}
	else
	{
		ASSERT(classPointer->m_location->m_instanceSpec.m_nullTerminated);

		MWORD objectSize;

		switch (reinterpret_cast<const StringClass&>(byteClass).Encoding)
		{
		case StringEncoding::Ansi:
		case StringEncoding::Utf8:
			objectSize = elementCount * sizeof(AnsiString::CU);
			break;
		case StringEncoding::Utf16:
			objectSize = elementCount * sizeof(Utf16String::CU);
			break;
		case StringEncoding::Utf32:
			objectSize = elementCount * sizeof(Utf32String::CU);
			break;
		default:
			__assume(false);
			break;
		}

		// TODO: Allocate the correct number of null term bytes based on the encoding
		objectSize += NULLTERMSIZE;

		VariantByteObject* newBytes = static_cast<VariantByteObject*>(allocObject(objectSize + SizeOfPointers(0), ote));
		ASSERT((objectSize > MaxSizeOfPoolObject && ote->heapSpace() == OTEFlags::NormalSpace)
			|| ote->heapSpace() == OTEFlags::PoolSpace);

		ASSERT(ote->getSize() == objectSize + SizeOfPointers(0));

		if (Initialized)
		{
			// Byte objects are initialized to zeros (but not the header)
			// Note that we round up to initialize to the next DWORD
			// This can be useful when working on a 32-bit word machine
			ZeroMemory(newBytes->m_fields, _ROUND2(objectSize, sizeof(DWORD)));
			classPointer->countUp();
		}
		else
		{
			// We still want to ensure the null terminator is set, even if not initializing the rest of the object
			*reinterpret_cast<NULLTERMTYPE*>(&newBytes->m_fields[objectSize - NULLTERMSIZE]) = 0;
		}

		ote->m_oteClass = classPointer;
		ote->beNullTerminated();
		HARDASSERT(ote->isBytes());
	}

	return reinterpret_cast<BytesOTE*>(ote);
}