Beispiel #1
0
bool StringCell::operator==(const StringCell &other) const
{
	if (byteLength() != other.byteLength())
	{
		return false;
	}

	if (dataIsInline())
	{
		auto thisInlineString = static_cast<const InlineStringCell*>(this);
		auto otherInlineString = static_cast<const InlineStringCell*>(&other);

		return memcmp(
				thisInlineString->inlineData(),
				otherInlineString->inlineData(),
				thisInlineString->inlineByteLength()) == 0;
	}
	else
	{
		auto thisHeapString = static_cast<const HeapStringCell*>(this);

		auto thisByteArray = thisHeapString->heapByteArray();
		auto otherByteArray = static_cast<const HeapStringCell*>(&other)->heapByteArray();

		return thisByteArray->isEqual(otherByteArray, thisHeapString->heapByteLength());
	}
}
Beispiel #2
0
StringCell* StringCell::fromSymbol(World &world, SymbolCell *symbol)
{
	alloc::SymbolRef symbolRef(world, symbol);
	void *cellPlacement = alloc::allocateCells(world);

	if (symbolRef->dataIsInline())
	{
		auto inlineSymbol = static_cast<InlineSymbolCell*>(symbolRef.data());

		auto inlineString = new (cellPlacement) InlineStringCell(
				inlineSymbol->inlineByteLength(),
				inlineSymbol->inlineCharLength()
		);

		// Copy the inline data over
		const void *srcData = inlineSymbol->inlineData();
		memcpy(inlineString->inlineData(), srcData, inlineSymbol->inlineByteLength());

		return inlineString;
	}
	else
	{
		auto heapSymbol = static_cast<HeapSymbolCell*>(symbolRef.data());

		// Share the heap symbols's byte array
		return new (cellPlacement) HeapStringCell(
				heapSymbol->heapByteArray()->ref(),
				heapSymbol->heapByteLength(),
				heapSymbol->heapCharLength()
		);
	}
}
Beispiel #3
0
bool SymbolCell::operator==(const SymbolCell &other) const
{
	if (isGlobalConstant() && other.isGlobalConstant())
	{
		// Constant folding guarantees this works
		return this == &other;
	}

	if (byteLength() != other.byteLength())
	{
		return false;
	}

	if (dataIsInline())
	{
		auto thisInlineSymbol = static_cast<const InlineSymbolCell*>(this);
		auto otherInlineSymbol = static_cast<const InlineSymbolCell*>(&other);

		return memcmp(
				thisInlineSymbol->inlineData(),
				otherInlineSymbol->inlineData(),
				thisInlineSymbol->inlineByteLength()) == 0;
	}
	else
	{
		auto thisHeapSymbol = static_cast<const HeapSymbolCell*>(this);

		auto thisByteArray = thisHeapSymbol->heapByteArray();
		auto otherByteArray = static_cast<const HeapSymbolCell*>(&other)->heapByteArray();

		return thisByteArray->isEqual(otherByteArray, thisHeapSymbol->heapByteLength());
	}
}
Beispiel #4
0
StringCell* StringCell::createUninitialized(World &world, ByteLengthType byteLength, CharLengthType charLength)
{
	void *cellPlacement = alloc::allocateCells(world);

	if (byteLength <= inlineDataSize())
	{
		// We can fit this string inline
		auto newString = new (cellPlacement) InlineStringCell(byteLength, charLength);

#ifndef NDEBUG
		if (byteLength < inlineDataSize())
		{
			// Explicitly terminate with non-NULL to catch users that assume we're NULL terminated internally
			newString->inlineData()[byteLength] = 0xff;
		}
#endif

		return newString;
	}
	else
	{
		// Allocate a new shared byte array
		SharedByteArray *newByteArray = SharedByteArray::createInstance(byteLength);

#ifndef NDEBUG
		if (newByteArray->capacity(byteLength) > byteLength)
		{
			newByteArray->data()[byteLength] = 0xff;
		}
#endif

		return new (cellPlacement) HeapStringCell(newByteArray, byteLength, charLength);
	}
}
Beispiel #5
0
SymbolCell* SymbolCell::fromUtf8Data(World &world, const std::uint8_t *data, ByteLengthType byteLength)
{
	const std::uint8_t *scanPtr = data;
	const std::uint8_t *endPtr = data + byteLength;

	// Validate the UTF-8 data
	const std::size_t charLength = utf8::validateData(scanPtr, endPtr);

	void *cellPlacement = alloc::allocateCells(world);

	if (byteLength <= inlineDataSize())
	{
		auto inlineSymbol = new (cellPlacement) InlineSymbolCell(byteLength, charLength);
		memcpy(inlineSymbol->inlineData(), data, byteLength);

		return inlineSymbol;
	}
	else
	{
		SharedByteArray *newByteArray = SharedByteArray::createUninitialised(byteLength);
		memcpy(newByteArray->data(), data, byteLength);

		return new (cellPlacement) HeapSymbolCell(newByteArray, byteLength, charLength);
	}
}
Beispiel #6
0
SymbolCell* SymbolCell::fromString(World &world, StringCell *string)
{
	void *cellPlacement = alloc::allocateCells(world);

	// Symbols must have the same inlining threshold as strings for the below logic to work
	static_assert(
			sizeof(InlineSymbolCell::m_inlineData) == sizeof(InlineStringCell::m_inlineData),
			"Symbols and strings must have the same inlining threshold"
	);

	if (string->dataIsInline())
	{
		auto inlineString = static_cast<InlineStringCell*>(string);

		auto inlineSymbol = new (cellPlacement) InlineSymbolCell(
				inlineString->inlineByteLength(),
				inlineString->inlineCharLength()
		);

		// Copy the inline data over
		const void *srcData = inlineString->inlineData();
		memcpy(inlineSymbol->inlineData(), srcData, inlineString->inlineByteLength());

		return inlineSymbol;
	}
	else
	{
		auto heapString = static_cast<HeapStringCell*>(string);

		// Share the heap strings's byte array
		return new (cellPlacement) HeapSymbolCell(
				heapString->heapByteArray()->ref(),
				heapString->heapByteLength(),
				heapString->heapCharLength()
		);
	}
}
Beispiel #7
0
SharedByteHash::ResultType StringCell::sharedByteHash() const
{
	if (dataIsInline())
	{
		auto inlineString = static_cast<const InlineStringCell*>(this);

		SharedByteHash byteHasher;
		return byteHasher(inlineString->inlineData(), inlineString->inlineByteLength());
	}
	else
	{
		auto heapString = static_cast<const HeapStringCell*>(this);
		return heapString->heapByteArray()->hashValue(heapString->heapByteLength());
	}
}