X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/runtime/SmallStrings.cpp?ds=sidebyside diff --git a/runtime/SmallStrings.cpp b/runtime/SmallStrings.cpp index 8741e9b..9c6a43a 100644 --- a/runtime/SmallStrings.cpp +++ b/runtime/SmallStrings.cpp @@ -26,18 +26,15 @@ #include "config.h" #include "SmallStrings.h" +#include "HeapRootVisitor.h" #include "JSGlobalObject.h" #include "JSString.h" +#include "JSCInlines.h" #include -#include +#include namespace JSC { -static inline bool isMarked(JSCell* string) -{ - return string && Heap::isMarked(string); -} - class SmallStringsStorage { WTF_MAKE_NONCOPYABLE(SmallStringsStorage); WTF_MAKE_FAST_ALLOCATED; public: @@ -56,91 +53,85 @@ private: SmallStringsStorage::SmallStringsStorage() { - UChar* characterBuffer = 0; + LChar* characterBuffer = 0; RefPtr baseString = StringImpl::createUninitialized(singleCharacterStringCount, characterBuffer); for (unsigned i = 0; i < singleCharacterStringCount; ++i) { characterBuffer[i] = i; - m_reps[i] = StringImpl::create(baseString, i, 1); + m_reps[i] = AtomicStringImpl::add(PassRefPtr(StringImpl::createSubstringSharingImpl(baseString, i, 1)).get()); } } SmallStrings::SmallStrings() + : m_emptyString(0) +#define JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE(name) , m_##name(0) + JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE) +#undef JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE + , m_nullObjectString(nullptr) + , m_undefinedObjectString(nullptr) + , m_needsToBeVisited(true) { COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); - clear(); -} -SmallStrings::~SmallStrings() -{ + for (unsigned i = 0; i < singleCharacterStringCount; ++i) + m_singleCharacterStrings[i] = 0; } -void SmallStrings::visitChildren(HeapRootVisitor& heapRootMarker) +void SmallStrings::initializeCommonStrings(VM& vm) { - /* - Our hypothesis is that small strings are very common. So, we cache them - to avoid GC churn. However, in cases where this hypothesis turns out to - be false -- including the degenerate case where all JavaScript execution - has terminated -- we don't want to waste memory. - - To test our hypothesis, we check if any small string has been marked. If - so, it's probably reasonable to mark the rest. If not, we clear the cache. - */ - - bool isAnyStringMarked = isMarked(m_emptyString); - for (unsigned i = 0; i < singleCharacterStringCount && !isAnyStringMarked; ++i) - isAnyStringMarked = isMarked(m_singleCharacterStrings[i]); - - if (!isAnyStringMarked) { - clear(); - return; - } - - if (m_emptyString) - heapRootMarker.mark(&m_emptyString); - for (unsigned i = 0; i < singleCharacterStringCount; ++i) { - if (m_singleCharacterStrings[i]) - heapRootMarker.mark(&m_singleCharacterStrings[i]); - } + createEmptyString(&vm); + for (unsigned i = 0; i <= maxSingleCharacterString; ++i) + createSingleCharacterString(&vm, i); +#define JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE(name) initialize(&vm, m_##name, #name); + JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE) +#undef JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE + initialize(&vm, m_nullObjectString, "[object Null]"); + initialize(&vm, m_undefinedObjectString, "[object Undefined]"); } -void SmallStrings::clear() +void SmallStrings::visitStrongReferences(SlotVisitor& visitor) { - m_emptyString = 0; - for (unsigned i = 0; i < singleCharacterStringCount; ++i) - m_singleCharacterStrings[i] = 0; + m_needsToBeVisited = false; + visitor.appendUnbarrieredPointer(&m_emptyString); + for (unsigned i = 0; i <= maxSingleCharacterString; ++i) + visitor.appendUnbarrieredPointer(m_singleCharacterStrings + i); +#define JSC_COMMON_STRINGS_ATTRIBUTE_VISIT(name) visitor.appendUnbarrieredPointer(&m_##name); + JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_VISIT) +#undef JSC_COMMON_STRINGS_ATTRIBUTE_VISIT + visitor.appendUnbarrieredPointer(&m_nullObjectString); + visitor.appendUnbarrieredPointer(&m_undefinedObjectString); } -unsigned SmallStrings::count() const +SmallStrings::~SmallStrings() { - unsigned count = 0; - if (m_emptyString) - ++count; - for (unsigned i = 0; i < singleCharacterStringCount; ++i) { - if (m_singleCharacterStrings[i]) - ++count; - } - return count; } -void SmallStrings::createEmptyString(JSGlobalData* globalData) +void SmallStrings::createEmptyString(VM* vm) { ASSERT(!m_emptyString); - m_emptyString = new (globalData) JSString(globalData, "", JSString::HasOtherOwner); + m_emptyString = JSString::createHasOtherOwner(*vm, StringImpl::empty()); + m_needsToBeVisited = true; } -void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigned char character) +void SmallStrings::createSingleCharacterString(VM* vm, unsigned char character) { if (!m_storage) - m_storage = adoptPtr(new SmallStringsStorage); + m_storage = std::make_unique(); ASSERT(!m_singleCharacterStrings[character]); - m_singleCharacterStrings[character] = new (globalData) JSString(globalData, PassRefPtr(m_storage->rep(character)), JSString::HasOtherOwner); + m_singleCharacterStrings[character] = JSString::createHasOtherOwner(*vm, PassRefPtr(m_storage->rep(character))); + m_needsToBeVisited = true; } StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character) { if (!m_storage) - m_storage = adoptPtr(new SmallStringsStorage); + m_storage = std::make_unique(); return m_storage->rep(character); } +void SmallStrings::initialize(VM* vm, JSString*& string, const char* value) +{ + string = JSString::create(*vm, Identifier::fromString(vm, value).impl()); + m_needsToBeVisited = true; +} + } // namespace JSC