1/*
2 * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "SmallStrings.h"
28
29#include "HeapRootVisitor.h"
30#include "JSGlobalObject.h"
31#include "JSString.h"
32#include "JSCInlines.h"
33#include <wtf/Noncopyable.h>
34#include <wtf/PassOwnPtr.h>
35#include <wtf/text/StringImpl.h>
36
37namespace JSC {
38
39class SmallStringsStorage {
40    WTF_MAKE_NONCOPYABLE(SmallStringsStorage); WTF_MAKE_FAST_ALLOCATED;
41public:
42    SmallStringsStorage();
43
44    StringImpl* rep(unsigned char character)
45    {
46        return m_reps[character].get();
47    }
48
49private:
50    static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
51
52    RefPtr<StringImpl> m_reps[singleCharacterStringCount];
53};
54
55SmallStringsStorage::SmallStringsStorage()
56{
57    LChar* characterBuffer = 0;
58    RefPtr<StringImpl> baseString = StringImpl::createUninitialized(singleCharacterStringCount, characterBuffer);
59    for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
60        characterBuffer[i] = i;
61        m_reps[i] = AtomicString::add(PassRefPtr<StringImpl>(StringImpl::createSubstringSharingImpl(baseString, i, 1)).get());
62    }
63}
64
65SmallStrings::SmallStrings()
66    : m_emptyString(0)
67#define JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE(name) , m_##name(0)
68    JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE)
69#undef JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE
70    , m_nullObjectString(nullptr)
71    , m_undefinedObjectString(nullptr)
72{
73    COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
74
75    for (unsigned i = 0; i < singleCharacterStringCount; ++i)
76        m_singleCharacterStrings[i] = 0;
77}
78
79void SmallStrings::initializeCommonStrings(VM& vm)
80{
81    createEmptyString(&vm);
82    for (unsigned i = 0; i <= maxSingleCharacterString; ++i)
83        createSingleCharacterString(&vm, i);
84#define JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE(name) initialize(&vm, m_##name, #name);
85    JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE)
86#undef JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE
87    initialize(&vm, m_nullObjectString, "[object Null]");
88    initialize(&vm, m_undefinedObjectString, "[object Undefined]");
89}
90
91void SmallStrings::visitStrongReferences(SlotVisitor& visitor)
92{
93    visitor.appendUnbarrieredPointer(&m_emptyString);
94    for (unsigned i = 0; i <= maxSingleCharacterString; ++i)
95        visitor.appendUnbarrieredPointer(m_singleCharacterStrings + i);
96#define JSC_COMMON_STRINGS_ATTRIBUTE_VISIT(name) visitor.appendUnbarrieredPointer(&m_##name);
97    JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_VISIT)
98#undef JSC_COMMON_STRINGS_ATTRIBUTE_VISIT
99    visitor.appendUnbarrieredPointer(&m_nullObjectString);
100    visitor.appendUnbarrieredPointer(&m_undefinedObjectString);
101}
102
103SmallStrings::~SmallStrings()
104{
105}
106
107void SmallStrings::createEmptyString(VM* vm)
108{
109    ASSERT(!m_emptyString);
110    m_emptyString = JSString::createHasOtherOwner(*vm, StringImpl::empty());
111}
112
113void SmallStrings::createSingleCharacterString(VM* vm, unsigned char character)
114{
115    if (!m_storage)
116        m_storage = adoptPtr(new SmallStringsStorage);
117    ASSERT(!m_singleCharacterStrings[character]);
118    m_singleCharacterStrings[character] = JSString::createHasOtherOwner(*vm, PassRefPtr<StringImpl>(m_storage->rep(character)));
119}
120
121StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character)
122{
123    if (!m_storage)
124        m_storage = adoptPtr(new SmallStringsStorage);
125    return m_storage->rep(character);
126}
127
128void SmallStrings::initialize(VM* vm, JSString*& string, const char* value) const
129{
130    string = JSString::create(*vm, StringImpl::create(value));
131}
132
133} // namespace JSC
134