Commit 44fb4f7d authored by barraclough@apple.com's avatar barraclough@apple.com

Change UStringImpl::create to CRASH if the string cannot be allocated,

rather than returning a null string (which will behave like a zero-length
string if used).

Reviewed by Geoff Garen.

Also move createRep function from UString to become new overloaded
UStringImpl::create methods.  In doing so, bring their behaviour closer to
being in line with WebCore::StringImpl, in removing the behaviour that they
can be used to produce null UStrings (ASSERT the char* provided is non-null).
This behaviour of converting null C-strings to null UStrings is inefficient
(cmompared to just using UString::null()), incompatible with WebCore::StringImpl's
behaviour, and may generate unexpected behaviour, since in many cases a null
UString can be used like an empty string.

With these changes UStringImpl need not have a concept of null impls, we can
start transitioning this to become an implementation detail of UString, that
internally it chooses to use a null-object rather than an actually zero impl
pointer.

* JavaScriptCore.exp:
* debugger/Debugger.cpp:
(JSC::Debugger::recompileAllJSFunctions):
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::calculatedFunctionName):
* parser/Parser.cpp:
(JSC::Parser::parse):
* profiler/Profile.cpp:
(JSC::Profile::Profile):
* profiler/ProfileGenerator.cpp:
(JSC::ProfileGenerator::stopProfiling):
* runtime/Error.cpp:
(JSC::Error::create):
(JSC::throwError):
* runtime/ExceptionHelpers.cpp:
(JSC::createError):
* runtime/Identifier.cpp:
(JSC::Identifier::add):
* runtime/PropertyNameArray.cpp:
(JSC::PropertyNameArray::add):
* runtime/UString.cpp:
(JSC::initializeUString):
(JSC::UString::UString):
(JSC::UString::operator=):
* runtime/UString.h:
(JSC::UString::isNull):
(JSC::UString::null):
(JSC::UString::rep):
(JSC::UString::UString):
* runtime/UStringImpl.cpp:
(JSC::UStringImpl::create):
* runtime/UStringImpl.h:



git-svn-id: svn://svn.chromium.org/blink/trunk@54464 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 5f4ec56c
2010-02-05 Gavin Barraclough <barraclough@apple.com>
Reviewed by Geoff Garen.
Change UStringImpl::create to CRASH if the string cannot be allocated,
rather than returning a null string (which will behave like a zero-length
string if used).
Also move createRep function from UString to become new overloaded
UStringImpl::create methods. In doing so, bring their behaviour closer to
being in line with WebCore::StringImpl, in removing the behaviour that they
can be used to produce null UStrings (ASSERT the char* provided is non-null).
This behaviour of converting null C-strings to null UStrings is inefficient
(cmompared to just using UString::null()), incompatible with WebCore::StringImpl's
behaviour, and may generate unexpected behaviour, since in many cases a null
UString can be used like an empty string.
With these changes UStringImpl need not have a concept of null impls, we can
start transitioning this to become an implementation detail of UString, that
internally it chooses to use a null-object rather than an actually zero impl
pointer.
* JavaScriptCore.exp:
* debugger/Debugger.cpp:
(JSC::Debugger::recompileAllJSFunctions):
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::calculatedFunctionName):
* parser/Parser.cpp:
(JSC::Parser::parse):
* profiler/Profile.cpp:
(JSC::Profile::Profile):
* profiler/ProfileGenerator.cpp:
(JSC::ProfileGenerator::stopProfiling):
* runtime/Error.cpp:
(JSC::Error::create):
(JSC::throwError):
* runtime/ExceptionHelpers.cpp:
(JSC::createError):
* runtime/Identifier.cpp:
(JSC::Identifier::add):
* runtime/PropertyNameArray.cpp:
(JSC::PropertyNameArray::add):
* runtime/UString.cpp:
(JSC::initializeUString):
(JSC::UString::UString):
(JSC::UString::operator=):
* runtime/UString.h:
(JSC::UString::isNull):
(JSC::UString::null):
(JSC::UString::rep):
(JSC::UString::UString):
* runtime/UStringImpl.cpp:
(JSC::UStringImpl::create):
* runtime/UStringImpl.h:
2010-02-05 Kwang Yul Seo <skyul@company100.net> 2010-02-05 Kwang Yul Seo <skyul@company100.net>
Reviewed by Eric Seidel. Reviewed by Eric Seidel.
......
...@@ -104,7 +104,6 @@ __ZN3JSC11JSByteArray15createStructureENS_7JSValueE ...@@ -104,7 +104,6 @@ __ZN3JSC11JSByteArray15createStructureENS_7JSValueE
__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE __ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
__ZN3JSC11ParserArena5resetEv __ZN3JSC11ParserArena5resetEv
__ZN3JSC11UStringImpl12sharedBufferEv __ZN3JSC11UStringImpl12sharedBufferEv
__ZN3JSC11UStringImpl6s_nullE
__ZN3JSC11UStringImpl7s_emptyE __ZN3JSC11UStringImpl7s_emptyE
__ZN3JSC11UStringImplD1Ev __ZN3JSC11UStringImplD1Ev
__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
...@@ -238,6 +237,7 @@ __ZN3JSC7UString4fromEd ...@@ -238,6 +237,7 @@ __ZN3JSC7UString4fromEd
__ZN3JSC7UString4fromEi __ZN3JSC7UString4fromEi
__ZN3JSC7UString4fromEj __ZN3JSC7UString4fromEj
__ZN3JSC7UString4fromEl __ZN3JSC7UString4fromEl
__ZN3JSC7UString9s_nullRepE
__ZN3JSC7UStringC1EPKc __ZN3JSC7UStringC1EPKc
__ZN3JSC7UStringC1EPKti __ZN3JSC7UStringC1EPKti
__ZN3JSC7UStringaSEPKc __ZN3JSC7UStringaSEPKc
......
...@@ -94,7 +94,7 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData) ...@@ -94,7 +94,7 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
// JavaScript in the inspector. // JavaScript in the inspector.
SourceProviderMap::const_iterator end = sourceProviders.end(); SourceProviderMap::const_iterator end = sourceProviders.end();
for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter) for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter)
sourceParsed(iter->second, SourceCode(iter->first), -1, 0); sourceParsed(iter->second, SourceCode(iter->first), -1, UString());
} }
JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject) JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
......
...@@ -50,11 +50,11 @@ const UString* DebuggerCallFrame::functionName() const ...@@ -50,11 +50,11 @@ const UString* DebuggerCallFrame::functionName() const
UString DebuggerCallFrame::calculatedFunctionName() const UString DebuggerCallFrame::calculatedFunctionName() const
{ {
if (!m_callFrame->codeBlock()) if (!m_callFrame->codeBlock())
return 0; return UString();
JSFunction* function = asFunction(m_callFrame->callee()); JSFunction* function = asFunction(m_callFrame->callee());
if (!function) if (!function)
return 0; return UString();
return function->calculatedDisplayName(m_callFrame); return function->calculatedDisplayName(m_callFrame);
} }
......
...@@ -50,7 +50,7 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg) ...@@ -50,7 +50,7 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
errMsg = &defaultErrMsg; errMsg = &defaultErrMsg;
*errLine = -1; *errLine = -1;
*errMsg = 0; *errMsg = UString();
Lexer& lexer = *globalData->lexer; Lexer& lexer = *globalData->lexer;
lexer.setCode(*m_source, m_arena); lexer.setCode(*m_source, m_arena);
......
...@@ -42,7 +42,7 @@ Profile::Profile(const UString& title, unsigned uid) ...@@ -42,7 +42,7 @@ Profile::Profile(const UString& title, unsigned uid)
{ {
// FIXME: When multi-threading is supported this will be a vector and calls // FIXME: When multi-threading is supported this will be a vector and calls
// into the profiler will need to know which thread it is executing on. // into the profiler will need to know which thread it is executing on.
m_head = ProfileNode::create(CallIdentifier("Thread_1", 0, 0), 0, 0); m_head = ProfileNode::create(CallIdentifier("Thread_1", UString(), 0), 0, 0);
} }
Profile::~Profile() Profile::~Profile()
......
...@@ -124,7 +124,7 @@ void ProfileGenerator::stopProfiling() ...@@ -124,7 +124,7 @@ void ProfileGenerator::stopProfiling()
m_currentNode = m_currentNode->parent(); m_currentNode = m_currentNode->parent();
if (double headSelfTime = m_head->selfTime()) { if (double headSelfTime = m_head->selfTime()) {
RefPtr<ProfileNode> idleNode = ProfileNode::create(CallIdentifier(NonJSExecution, 0, 0), m_head.get(), m_head.get()); RefPtr<ProfileNode> idleNode = ProfileNode::create(CallIdentifier(NonJSExecution, UString(), 0), m_head.get(), m_head.get());
idleNode->setTotalTime(headSelfTime); idleNode->setTotalTime(headSelfTime);
idleNode->setSelfTime(headSelfTime); idleNode->setSelfTime(headSelfTime);
......
...@@ -94,7 +94,7 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const UString& message, ...@@ -94,7 +94,7 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const UString& message,
JSObject* Error::create(ExecState* exec, ErrorType type, const char* message) JSObject* Error::create(ExecState* exec, ErrorType type, const char* message)
{ {
return create(exec, type, message, -1, -1, NULL); return create(exec, type, message, -1, -1, UString());
} }
JSObject* throwError(ExecState* exec, JSObject* error) JSObject* throwError(ExecState* exec, JSObject* error)
...@@ -105,21 +105,21 @@ JSObject* throwError(ExecState* exec, JSObject* error) ...@@ -105,21 +105,21 @@ JSObject* throwError(ExecState* exec, JSObject* error)
JSObject* throwError(ExecState* exec, ErrorType type) JSObject* throwError(ExecState* exec, ErrorType type)
{ {
JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL); JSObject* error = Error::create(exec, type, UString(), -1, -1, UString());
exec->setException(error); exec->setException(error);
return error; return error;
} }
JSObject* throwError(ExecState* exec, ErrorType type, const UString& message) JSObject* throwError(ExecState* exec, ErrorType type, const UString& message)
{ {
JSObject* error = Error::create(exec, type, message, -1, -1, NULL); JSObject* error = Error::create(exec, type, message, -1, -1, UString());
exec->setException(error); exec->setException(error);
return error; return error;
} }
JSObject* throwError(ExecState* exec, ErrorType type, const char* message) JSObject* throwError(ExecState* exec, ErrorType type, const char* message)
{ {
JSObject* error = Error::create(exec, type, message, -1, -1, NULL); JSObject* error = Error::create(exec, type, message, -1, -1, UString());
exec->setException(error); exec->setException(error);
return error; return error;
} }
......
...@@ -58,7 +58,7 @@ JSValue createInterruptedExecutionException(JSGlobalData* globalData) ...@@ -58,7 +58,7 @@ JSValue createInterruptedExecutionException(JSGlobalData* globalData)
static JSValue createError(ExecState* exec, ErrorType e, const char* msg) static JSValue createError(ExecState* exec, ErrorType e, const char* msg)
{ {
return Error::create(exec, e, msg, -1, -1, 0); return Error::create(exec, e, msg, -1, -1, UString());
} }
JSValue createStackOverflowError(ExecState* exec) JSValue createStackOverflowError(ExecState* exec)
......
...@@ -124,8 +124,9 @@ struct CStringTranslator { ...@@ -124,8 +124,9 @@ struct CStringTranslator {
PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c) PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c)
{ {
if (!c) { if (!c) {
UString::Rep::null().hash(); UString::Rep* rep = UString::null().rep();
return &UString::Rep::null(); rep->hash();
return rep;
} }
if (!c[0]) { if (!c[0]) {
UString::Rep::empty().hash(); UString::Rep::empty().hash();
......
...@@ -30,7 +30,7 @@ static const size_t setThreshold = 20; ...@@ -30,7 +30,7 @@ static const size_t setThreshold = 20;
void PropertyNameArray::add(UString::Rep* identifier) void PropertyNameArray::add(UString::Rep* identifier)
{ {
ASSERT(identifier == &UString::Rep::null() || identifier == &UString::Rep::empty() || identifier->isIdentifier()); ASSERT(identifier == UString::null().rep() || identifier == &UString::Rep::empty() || identifier->isIdentifier());
size_t size = m_data->propertyNameVector().size(); size_t size = m_data->propertyNameVector().size();
if (size < setThreshold) { if (size < setThreshold) {
......
...@@ -149,61 +149,26 @@ bool operator==(const CString& c1, const CString& c2) ...@@ -149,61 +149,26 @@ bool operator==(const CString& c1, const CString& c2)
// These static strings are immutable, except for rc, whose initial value is chosen to // These static strings are immutable, except for rc, whose initial value is chosen to
// reduce the possibility of it becoming zero due to ref/deref not being thread-safe. // reduce the possibility of it becoming zero due to ref/deref not being thread-safe.
static UChar sharedEmptyChar; static UChar sharedEmptyChar;
UStringImpl* UStringImpl::s_null;
UStringImpl* UStringImpl::s_empty; UStringImpl* UStringImpl::s_empty;
UString* UString::nullUString;
UString::Rep* UString::s_nullRep;
UString* UString::s_nullUString;
void initializeUString() void initializeUString()
{ {
UStringImpl::s_null = new UStringImpl(0, 0, UStringImpl::ConstructStaticString);
UStringImpl::s_empty = new UStringImpl(&sharedEmptyChar, 0, UStringImpl::ConstructStaticString); UStringImpl::s_empty = new UStringImpl(&sharedEmptyChar, 0, UStringImpl::ConstructStaticString);
UString::nullUString = new UString;
}
static PassRefPtr<UString::Rep> createRep(const char* c)
{
if (!c)
return &UString::Rep::null();
if (!c[0])
return &UString::Rep::empty();
size_t length = strlen(c);
UChar* d;
PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, d);
if (!result)
return &UString::Rep::null();
for (size_t i = 0; i < length; i++)
d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
return result;
}
static inline PassRefPtr<UString::Rep> createRep(const char* c, int length)
{
if (!c)
return &UString::Rep::null();
if (!length)
return &UString::Rep::empty();
UChar* d;
PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, d);
if (!result)
return &UString::Rep::null();
for (int i = 0; i < length; i++) UString::s_nullRep = new UStringImpl(0, 0, UStringImpl::ConstructStaticString);
d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend UString::s_nullUString = new UString;
return result;
} }
UString::UString(const char* c) UString::UString(const char* c)
: m_rep(createRep(c)) : m_rep(Rep::create(c))
{ {
} }
UString::UString(const char* c, int length) UString::UString(const char* c, int length)
: m_rep(createRep(c, length)) : m_rep(Rep::create(c, length))
{ {
} }
...@@ -459,7 +424,7 @@ char* UString::ascii() const ...@@ -459,7 +424,7 @@ char* UString::ascii() const
UString& UString::operator=(const char* c) UString& UString::operator=(const char* c)
{ {
if (!c) { if (!c) {
m_rep = &Rep::null(); m_rep = s_nullRep;
return *this; return *this;
} }
...@@ -475,7 +440,7 @@ UString& UString::operator=(const char* c) ...@@ -475,7 +440,7 @@ UString& UString::operator=(const char* c)
for (int i = 0; i < l; i++) for (int i = 0; i < l; i++)
d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
} else } else
makeNull(); m_rep = s_nullRep;;
return *this; return *this;
} }
...@@ -888,16 +853,4 @@ CString UString::UTF8String(bool strict) const ...@@ -888,16 +853,4 @@ CString UString::UTF8String(bool strict) const
return CString(buffer.data(), p - buffer.data()); return CString(buffer.data(), p - buffer.data());
} }
// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
NEVER_INLINE void UString::makeNull()
{
m_rep = &Rep::null();
}
// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
NEVER_INLINE UString::Rep* UString::nullRep()
{
return &Rep::null();
}
} // namespace JSC } // namespace JSC
...@@ -157,7 +157,7 @@ namespace JSC { ...@@ -157,7 +157,7 @@ namespace JSC {
const UChar* data() const { return m_rep->data(); } const UChar* data() const { return m_rep->data(); }
bool isNull() const { return m_rep == &Rep::null(); } bool isNull() const { return m_rep == s_nullRep; }
bool isEmpty() const { return !m_rep->size(); } bool isEmpty() const { return !m_rep->size(); }
bool is8Bit() const; bool is8Bit() const;
...@@ -183,10 +183,9 @@ namespace JSC { ...@@ -183,10 +183,9 @@ namespace JSC {
UString substr(int pos = 0, int len = -1) const; UString substr(int pos = 0, int len = -1) const;
static const UString& null() { return *nullUString; } static const UString& null() { return *s_nullUString; }
Rep* rep() const { return m_rep.get(); } Rep* rep() const { return m_rep.get(); }
static Rep* nullRep();
UString(PassRefPtr<Rep> r) UString(PassRefPtr<Rep> r)
: m_rep(r) : m_rep(r)
...@@ -197,10 +196,10 @@ namespace JSC { ...@@ -197,10 +196,10 @@ namespace JSC {
size_t cost() const { return m_rep->cost(); } size_t cost() const { return m_rep->cost(); }
private: private:
void makeNull();
RefPtr<Rep> m_rep; RefPtr<Rep> m_rep;
static UString* nullUString;
JS_EXPORTDATA static Rep* s_nullRep;
static UString* s_nullUString;
friend void initializeUString(); friend void initializeUString();
friend bool operator==(const UString&, const UString&); friend bool operator==(const UString&, const UString&);
...@@ -255,7 +254,7 @@ namespace JSC { ...@@ -255,7 +254,7 @@ namespace JSC {
int compare(const UString&, const UString&); int compare(const UString&, const UString&);
inline UString::UString() inline UString::UString()
: m_rep(&Rep::null()) : m_rep(s_nullRep)
{ {
} }
......
...@@ -34,7 +34,44 @@ using namespace WTF::Unicode; ...@@ -34,7 +34,44 @@ using namespace WTF::Unicode;
using namespace std; using namespace std;
namespace JSC { namespace JSC {
PassRefPtr<UStringImpl> UStringImpl::create(const char* c)
{
ASSERT(c);
if (!c[0])
return &UStringImpl::empty();
size_t length = strlen(c);
UChar* d;
PassRefPtr<UStringImpl> result = UStringImpl::createUninitialized(length, d);
for (size_t i = 0; i < length; i++)
d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
return result;
}
PassRefPtr<UStringImpl> UStringImpl::create(const char* c, int length)
{
ASSERT(c);
if (!length)
return &UStringImpl::empty();
UChar* d;
PassRefPtr<UStringImpl> result = UStringImpl::createUninitialized(length, d);
for (int i = 0; i < length; i++)
d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
return result;
}
PassRefPtr<UStringImpl> UStringImpl::create(const UChar* buffer, int length)
{
UChar* newBuffer;
PassRefPtr<UStringImpl> impl = createUninitialized(length, newBuffer);
copyChars(newBuffer, buffer, length);
return impl;
}
SharedUChar* UStringImpl::baseSharedBuffer() SharedUChar* UStringImpl::baseSharedBuffer()
{ {
ASSERT((bufferOwnership() == BufferShared) ASSERT((bufferOwnership() == BufferShared)
......
...@@ -92,15 +92,9 @@ public: ...@@ -92,15 +92,9 @@ public:
return &empty(); return &empty();
} }
static PassRefPtr<UStringImpl> create(const UChar* buffer, int length) static PassRefPtr<UStringImpl> create(const char* c);
{ static PassRefPtr<UStringImpl> create(const char* c, int length);
UChar* newBuffer; static PassRefPtr<UStringImpl> create(const UChar* buffer, int length);
if (PassRefPtr<UStringImpl> impl = tryCreateUninitialized(length, newBuffer)) {
copyChars(newBuffer, buffer, length);
return impl;
}
return &null();
}
static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, int offset, int length) static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, int offset, int length)
{ {
...@@ -180,7 +174,6 @@ public: ...@@ -180,7 +174,6 @@ public:
static unsigned computeHash(const char* s, int length) { ASSERT(length >= 0); return WTF::stringHash(s, length); } static unsigned computeHash(const char* s, int length) { ASSERT(length >= 0); return WTF::stringHash(s, length); }
static unsigned computeHash(const char* s) { return WTF::stringHash(s); } static unsigned computeHash(const char* s) { return WTF::stringHash(s); }
static UStringImpl& null() { return *s_null; }
static UStringImpl& empty() { return *s_empty; } static UStringImpl& empty() { return *s_empty; }
ALWAYS_INLINE void checkConsistency() const ALWAYS_INLINE void checkConsistency() const
...@@ -288,7 +281,6 @@ private: ...@@ -288,7 +281,6 @@ private:
mutable unsigned m_isIdentifier : 1; mutable unsigned m_isIdentifier : 1;
UntypedPtrAndBitfield m_dataBuffer; UntypedPtrAndBitfield m_dataBuffer;
JS_EXPORTDATA static UStringImpl* s_null;
JS_EXPORTDATA static UStringImpl* s_empty; JS_EXPORTDATA static UStringImpl* s_empty;
friend class JIT; friend class JIT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment