Add reference counter in CompressibleString

* remove stack searching to check if CompressibleString is in use
* add ref counter instead

Signed-off-by: HyukWoo Park <hyukwoo.park@samsung.com>
This commit is contained in:
HyukWoo Park 2021-12-10 18:48:35 +09:00
commit b51839b7b9
4 changed files with 30 additions and 26 deletions

View file

@ -47,6 +47,7 @@ CompressibleString::CompressibleString(VMInstance* instance)
: String()
, m_isOwnerMayFreed(false)
, m_isCompressed(false)
, m_refCount(0)
, m_vmInstance(instance)
, m_lastUsedTickcount(fastTickCount())
{
@ -56,6 +57,7 @@ CompressibleString::CompressibleString(VMInstance* instance)
v.push_back(this);
GC_REGISTER_FINALIZER_NO_ORDER(this, [](void* obj, void*) {
CompressibleString* self = (CompressibleString*)obj;
ASSERT(self->refCount() == 0);
if (self->isCompressed()) {
self->clearCompressedData();
} else {
@ -158,7 +160,8 @@ void CompressibleString::clearCompressedData()
bool CompressibleString::compress()
{
ASSERT(!m_isCompressed);
if (UNLIKELY(!m_bufferData.length)) {
if (UNLIKELY(!m_bufferData.length || !!m_refCount)) {
ESCARGOT_LOG_INFO("Compression Failed due to string usage in stack\n");
return false;
}
@ -188,23 +191,10 @@ void CompressibleString::decompress()
constexpr static const size_t g_compressChunkSize = 1044465;
static_assert(LZ4_COMPRESSBOUND(g_compressChunkSize) == 1024 * 1024, "");
static ATTRIBUTE_NO_SANITIZE_ADDRESS bool testPointerExistsOnStack(size_t* start, size_t* end, const void* ptr)
{
while (start != end) {
if (UNLIKELY(*start == (size_t)ptr)) {
// if there is reference on stack, we cannot compress string.
return true;
}
start++;
}
return false;
}
template <typename StringType>
bool CompressibleString::compressWorker(void* callerSP)
{
ASSERT(!m_isCompressed);
ASSERT(!m_isCompressed && !m_refCount);
ASSERT(m_bufferData.length > 0);
#if defined(STACK_GROWS_DOWN)
@ -215,11 +205,6 @@ bool CompressibleString::compressWorker(void* callerSP)
size_t* end = (size_t*)((size_t)callerSP & ~(sizeof(size_t) - 1));
#endif
if (testPointerExistsOnStack(start, end, m_bufferData.buffer)) {
ESCARGOT_LOG_INFO("Compression Failed due to string usage in stack\n");
return false;
}
size_t originByteLength = m_bufferData.length * sizeof(StringType);
int lastBoundLength = 0;
char* tempBuffer = nullptr;

View file

@ -78,7 +78,8 @@ public:
if (isCompressed()) {
decompress();
}
return StringBufferAccessData(m_bufferData.has8BitContent, m_bufferData.length, const_cast<void*>(m_bufferData.buffer));
return StringBufferAccessData(m_bufferData.has8BitContent, m_bufferData.length, const_cast<void*>(m_bufferData.buffer), &m_refCount);
}
bool isCompressed()
@ -86,6 +87,11 @@ public:
return m_isCompressed;
}
size_t refCount()
{
return m_refCount;
}
void* operator new(size_t);
void* operator new[](size_t) = delete;
void operator delete[](void*) = delete;
@ -118,6 +124,7 @@ private:
bool m_isOwnerMayFreed;
bool m_isCompressed;
size_t m_refCount; // reference count representing the usage of this CompressibleString
VMInstance* m_vmInstance;
uint64_t m_lastUsedTickcount;
typedef Vector<CompressedElement, GCUtil::gc_malloc_allocator<CompressedElement>> CompressedDataVector;

View file

@ -100,12 +100,27 @@ struct StringBufferAccessData {
};
void* extraData;
StringBufferAccessData(bool has8Bit, size_t len, void* buffer, void* extraDataKeepInStack = nullptr)
StringBufferAccessData(bool has8Bit, size_t len, void* buffer, void* extraDataToKeep = nullptr)
: has8BitContent(has8Bit)
, length(len)
, buffer(buffer)
, extraData(extraDataKeepInStack)
, extraData(extraDataToKeep)
{
if (extraData) {
// increase refCount in CompressibleString
size_t& count = *reinterpret_cast<size_t*>(extraData);
count++;
}
}
~StringBufferAccessData()
{
if (extraData) {
// decrease refCount in CompressibleString
size_t& count = *reinterpret_cast<size_t*>(extraData);
ASSERT(count > 0);
count--;
}
}
char16_t uncheckedCharAtFor8Bit(size_t idx) const

View file

@ -139,9 +139,6 @@ protected:
ASSERT(m_bufferData.hasSpecialImpl);
StringBufferAccessData r = m_bufferData.bufferAsString->bufferAccessData();
// keep original buffer pointer in stack
// without this, compressible string can free this pointer
r.extraData = const_cast<void*>(r.buffer);
r.length = m_bufferData.length;
if (r.has8BitContent) {
r.bufferAs8Bit += m_start;