source: webkit/trunk/JavaScriptCore/runtime/UStringImpl.cpp@ 55943

Last change on this file since 55943 was 55943, checked in by [email protected], 15 years ago

Bug 36075 - Clean up screwyness re static string impls & Identifiers.

Reviewed by Oliver Hunt.

JavaScriptCore:

  • API/JSClassRef.cpp:

(OpaqueJSClass::~OpaqueJSClass): Classname may be null/empty, and these are an identifer. This is okay, since the null/empty strings are shared across all threads.

(JSC::Identifier::add): No need to explicitly hash null reps, this is done in the ststic UStringImpl constructor.
(JSC::Identifier::addSlowCase): UStringImpl::empty() handled & checkCurrentIdentifierTable now called in the header.
(JSC::Identifier::checkCurrentIdentifierTable): Replaces checkSameIdentifierTable (this no longer checked the rep since the identifierTable pointer was removed from UString::Rep long ago).

  • runtime/Identifier.h:

(JSC::Identifier::add): Replace call to checkSameIdentifierTable with call to checkCurrentIdentifierTable at head of function.

  • runtime/UStringImpl.cpp:

(JSC::UStringImpl::~UStringImpl): Remove call to checkConsistency - this function no longer checks anything interesting.

  • runtime/UStringImpl.h:

(JSC::UStringOrRopeImpl::UStringOrRopeImpl): Set s_refCountFlagIsIdentifier in static constructor.
(JSC::UStringImpl::UStringImpl): remove calls to checkConsistency (see above), add new ASSERT to substring constructor.
(JSC::UStringImpl::setHash): ASSERT not static (static strings set the hash in their constructor, should not reach this code path).
(JSC::UStringImpl::create): Add missing ASSERT.
(JSC::UStringImpl::setIsIdentifier): ASSERT !isStatic() (static strings hash set in constructor).

WebCore:

  • platform/text/StringImpl.cpp:

(WebCore::StringImpl::~StringImpl): Add ASSERT
(WebCore::StringImpl::sharedBuffer): Add ASSERT

  • platform/text/StringImpl.h:

(WebCore::StringImpl::setHash): Add ASSERT
(WebCore::StringImpl::isStatic): added.

File size: 5.9 KB
Line 
1/*
2 * Copyright (C) 2009 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 "UStringImpl.h"
28
29#include "Identifier.h"
30#include "StdLibExtras.h"
31#include "UString.h"
32#include <wtf/unicode/UTF8.h>
33
34using namespace WTF::Unicode;
35using namespace std;
36
37namespace JSC {
38
39static const unsigned minLengthToShare = 20;
40
41UStringImpl::~UStringImpl()
42{
43 ASSERT(!isStatic());
44
45 if (isIdentifier())
46 Identifier::remove(this);
47
48 BufferOwnership ownership = bufferOwnership();
49 if (ownership != BufferInternal) {
50 if (ownership == BufferOwned) {
51 ASSERT(!m_sharedBuffer);
52 ASSERT(m_data);
53 fastFree(const_cast<UChar*>(m_data));
54 } else if (ownership == BufferSubstring) {
55 ASSERT(m_substringBuffer);
56 m_substringBuffer->deref();
57 } else {
58 ASSERT(ownership == BufferShared);
59 ASSERT(m_sharedBuffer);
60 m_sharedBuffer->deref();
61 }
62 }
63}
64
65UStringImpl* UStringImpl::empty()
66{
67 // A non-null pointer at an invalid address (in page zero) so that if it were to be accessed we
68 // should catch the error with fault (however it should be impossible to access, since length is zero).
69 static const UChar* invalidNonNullUCharPtr = reinterpret_cast<UChar*>(static_cast<intptr_t>(1));
70 DEFINE_STATIC_LOCAL(UStringImpl, emptyString, (invalidNonNullUCharPtr, 0, ConstructStaticString));
71 return &emptyString;
72}
73
74PassRefPtr<UStringImpl> UStringImpl::createUninitialized(unsigned length, UChar*& data)
75{
76 if (!length) {
77 data = 0;
78 return empty();
79 }
80
81 // Allocate a single buffer large enough to contain the StringImpl
82 // struct as well as the data which it contains. This removes one
83 // heap allocation from this call.
84 if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar)))
85 CRASH();
86 size_t size = sizeof(UStringImpl) + length * sizeof(UChar);
87 UStringImpl* string = static_cast<UStringImpl*>(fastMalloc(size));
88
89 data = reinterpret_cast<UChar*>(string + 1);
90 return adoptRef(new (string) UStringImpl(length));
91}
92
93PassRefPtr<UStringImpl> UStringImpl::create(const UChar* characters, unsigned length)
94{
95 if (!characters || !length)
96 return empty();
97
98 UChar* data;
99 PassRefPtr<UStringImpl> string = createUninitialized(length, data);
100 memcpy(data, characters, length * sizeof(UChar));
101 return string;
102}
103
104PassRefPtr<UStringImpl> UStringImpl::create(const char* characters, unsigned length)
105{
106 if (!characters || !length)
107 return empty();
108
109 UChar* data;
110 PassRefPtr<UStringImpl> string = createUninitialized(length, data);
111 for (unsigned i = 0; i != length; ++i) {
112 unsigned char c = characters[i];
113 data[i] = c;
114 }
115 return string;
116}
117
118PassRefPtr<UStringImpl> UStringImpl::create(const char* string)
119{
120 if (!string)
121 return empty();
122 return create(string, strlen(string));
123}
124
125PassRefPtr<UStringImpl> UStringImpl::create(PassRefPtr<SharedUChar> sharedBuffer, const UChar* buffer, unsigned length)
126{
127 if (!length)
128 return empty();
129 return adoptRef(new UStringImpl(buffer, length, sharedBuffer));
130}
131
132SharedUChar* UStringImpl::sharedBuffer()
133{
134 if (m_length < minLengthToShare)
135 return 0;
136 // All static strings are smaller that the minimim length to share.
137 ASSERT(!isStatic());
138
139 BufferOwnership ownership = bufferOwnership();
140
141 if (ownership == BufferInternal)
142 return 0;
143 if (ownership == BufferSubstring)
144 return m_substringBuffer->sharedBuffer();
145 if (ownership == BufferOwned) {
146 ASSERT(!m_sharedBuffer);
147 m_sharedBuffer = SharedUChar::create(new SharableUChar(m_data)).releaseRef();
148 m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
149 }
150
151 ASSERT(bufferOwnership() == BufferShared);
152 ASSERT(m_sharedBuffer);
153 return m_sharedBuffer;
154}
155
156void URopeImpl::derefFibersNonRecursive(Vector<URopeImpl*, 32>& workQueue)
157{
158 unsigned length = fiberCount();
159 for (unsigned i = 0; i < length; ++i) {
160 Fiber& fiber = fibers(i);
161 if (fiber->isRope()) {
162 URopeImpl* nextRope = static_cast<URopeImpl*>(fiber);
163 if (nextRope->hasOneRef())
164 workQueue.append(nextRope);
165 else
166 nextRope->deref();
167 } else
168 static_cast<UStringImpl*>(fiber)->deref();
169 }
170}
171
172void URopeImpl::destructNonRecursive()
173{
174 Vector<URopeImpl*, 32> workQueue;
175
176 derefFibersNonRecursive(workQueue);
177 delete this;
178
179 while (!workQueue.isEmpty()) {
180 URopeImpl* rope = workQueue.last();
181 workQueue.removeLast();
182 rope->derefFibersNonRecursive(workQueue);
183 delete rope;
184 }
185}
186
187} // namespace JSC
Note: See TracBrowser for help on using the repository browser.