X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4e4e5a6f2694187498445a6ac6f1634ce8141119..40a37d088818fc2fbeba2ef850dbcaaf294befbf:/runtime/SmallStrings.cpp diff --git a/runtime/SmallStrings.cpp b/runtime/SmallStrings.cpp index 0f5df4a..a4bdb0c 100644 --- a/runtime/SmallStrings.cpp +++ b/runtime/SmallStrings.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,116 +26,108 @@ #include "config.h" #include "SmallStrings.h" +#include "HeapRootVisitor.h" #include "JSGlobalObject.h" #include "JSString.h" - +#include "JSCInlines.h" #include +#include +#include namespace JSC { -static const unsigned numCharactersToStore = 0x100; -static inline bool isMarked(JSString* string) -{ - return string && Heap::isCellMarked(string); -} - -class SmallStringsStorage : public Noncopyable { +class SmallStringsStorage { + WTF_MAKE_NONCOPYABLE(SmallStringsStorage); WTF_MAKE_FAST_ALLOCATED; public: SmallStringsStorage(); - UString::Rep* rep(unsigned char character) { return m_reps[character].get(); } + StringImpl* rep(unsigned char character) + { + return m_reps[character].get(); + } private: - RefPtr m_reps[numCharactersToStore]; + static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1; + + RefPtr m_reps[singleCharacterStringCount]; }; SmallStringsStorage::SmallStringsStorage() { - UChar* characterBuffer = 0; - RefPtr baseString = UStringImpl::createUninitialized(numCharactersToStore, characterBuffer); - for (unsigned i = 0; i < numCharactersToStore; ++i) { + LChar* characterBuffer = 0; + RefPtr baseString = StringImpl::createUninitialized(singleCharacterStringCount, characterBuffer); + for (unsigned i = 0; i < singleCharacterStringCount; ++i) { characterBuffer[i] = i; - m_reps[i] = UStringImpl::create(baseString, i, 1); + m_reps[i] = AtomicString::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) { - COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); - clear(); -} + COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); -SmallStrings::~SmallStrings() -{ + for (unsigned i = 0; i < singleCharacterStringCount; ++i) + m_singleCharacterStrings[i] = 0; } -void SmallStrings::markChildren(MarkStack& markStack) +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 < numCharactersToStore && !isAnyStringMarked; ++i) - isAnyStringMarked = isMarked(m_singleCharacterStrings[i]); - - if (!isAnyStringMarked) { - clear(); - return; - } - - if (m_emptyString) - markStack.append(m_emptyString); - for (unsigned i = 0; i < numCharactersToStore; ++i) { - if (m_singleCharacterStrings[i]) - markStack.append(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 < numCharactersToStore; ++i) - m_singleCharacterStrings[i] = 0; + 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 < numCharactersToStore; ++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()); } -void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigned char character) +void SmallStrings::createSingleCharacterString(VM* vm, unsigned char character) { if (!m_storage) - m_storage.set(new SmallStringsStorage); + m_storage = adoptPtr(new SmallStringsStorage); ASSERT(!m_singleCharacterStrings[character]); - m_singleCharacterStrings[character] = new (globalData) JSString(globalData, m_storage->rep(character), JSString::HasOtherOwner); + m_singleCharacterStrings[character] = JSString::createHasOtherOwner(*vm, PassRefPtr(m_storage->rep(character))); } -UString::Rep* SmallStrings::singleCharacterStringRep(unsigned char character) +StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character) { if (!m_storage) - m_storage.set(new SmallStringsStorage); + m_storage = adoptPtr(new SmallStringsStorage); return m_storage->rep(character); } +void SmallStrings::initialize(VM* vm, JSString*& string, const char* value) const +{ + string = JSString::create(*vm, StringImpl::create(value)); +} + } // namespace JSC