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>
Reviewed by Eric Seidel.
......
......@@ -104,7 +104,6 @@ __ZN3JSC11JSByteArray15createStructureENS_7JSValueE
__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
__ZN3JSC11ParserArena5resetEv
__ZN3JSC11UStringImpl12sharedBufferEv
__ZN3JSC11UStringImpl6s_nullE
__ZN3JSC11UStringImpl7s_emptyE
__ZN3JSC11UStringImplD1Ev
__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
......@@ -238,6 +237,7 @@ __ZN3JSC7UString4fromEd
__ZN3JSC7UString4fromEi
__ZN3JSC7UString4fromEj
__ZN3JSC7UString4fromEl
__ZN3JSC7UString9s_nullRepE
__ZN3JSC7UStringC1EPKc
__ZN3JSC7UStringC1EPKti
__ZN3JSC7UStringaSEPKc
......
......@@ -94,7 +94,7 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
// JavaScript in the inspector.
SourceProviderMap::const_iterator end = sourceProviders.end();
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)
......
......@@ -50,11 +50,11 @@ const UString* DebuggerCallFrame::functionName() const
UString DebuggerCallFrame::calculatedFunctionName() const
{
if (!m_callFrame->codeBlock())
return 0;
return UString();
JSFunction* function = asFunction(m_callFrame->callee());
if (!function)
return 0;
return UString();
return function->calculatedDisplayName(m_callFrame);
}
......
......@@ -50,7 +50,7 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
errMsg = &defaultErrMsg;
*errLine = -1;
*errMsg = 0;
*errMsg = UString();
Lexer& lexer = *globalData->lexer;
lexer.setCode(*m_source, m_arena);
......
......@@ -42,7 +42,7 @@ Profile::Profile(const UString& title, unsigned uid)
{
// 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.
m_head = ProfileNode::create(CallIdentifier("Thread_1", 0, 0), 0, 0);
m_head = ProfileNode::create(CallIdentifier("Thread_1", UString(), 0), 0, 0);
}
Profile::~Profile()
......
......@@ -124,7 +124,7 @@ void ProfileGenerator::stopProfiling()
m_currentNode = m_currentNode->parent();
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->setSelfTime(headSelfTime);
......
......@@ -94,7 +94,7 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const UString& 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)
......@@ -105,21 +105,21 @@ JSObject* throwError(ExecState* exec, JSObject* error)
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);
return error;
}
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);
return error;
}
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);
return error;
}
......
......@@ -58,7 +58,7 @@ JSValue createInterruptedExecutionException(JSGlobalData* globalData)
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)
......
......@@ -124,8 +124,9 @@ struct CStringTranslator {
PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c)
{
if (!c) {
UString::Rep::null().hash();
return &UString::Rep::null();
UString::Rep* rep = UString::null().rep();
rep->hash();
return rep;
}
if (!c[0]) {
UString::Rep::empty().hash();
......
......@@ -30,7 +30,7 @@ static const size_t setThreshold = 20;
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();
if (size < setThreshold) {
......
......@@ -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
// reduce the possibility of it becoming zero due to ref/deref not being thread-safe.
static UChar sharedEmptyChar;
UStringImpl* UStringImpl::s_null;
UStringImpl* UStringImpl::s_empty;
UString* UString::nullUString;
UString::Rep* UString::s_nullRep;
UString* UString::s_nullUString;
void initializeUString()
{
UStringImpl::s_null = new UStringImpl(0, 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++)
d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
return result;
UString::s_nullRep = new UStringImpl(0, 0, UStringImpl::ConstructStaticString);
UString::s_nullUString = new UString;
}
UString::UString(const char* c)
: m_rep(createRep(c))
: m_rep(Rep::create(c))
{
}
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
UString& UString::operator=(const char* c)
{
if (!c) {
m_rep = &Rep::null();
m_rep = s_nullRep;
return *this;
}
......@@ -475,7 +440,7 @@ UString& UString::operator=(const char* c)
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
} else
makeNull();
m_rep = s_nullRep;;
return *this;
}
......@@ -888,16 +853,4 @@ CString UString::UTF8String(bool strict) const
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
......@@ -157,7 +157,7 @@ namespace JSC {
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 is8Bit() const;
......@@ -183,10 +183,9 @@ namespace JSC {
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(); }
static Rep* nullRep();
UString(PassRefPtr<Rep> r)
: m_rep(r)
......@@ -197,10 +196,10 @@ namespace JSC {
size_t cost() const { return m_rep->cost(); }
private:
void makeNull();
RefPtr<Rep> m_rep;
static UString* nullUString;
JS_EXPORTDATA static Rep* s_nullRep;
static UString* s_nullUString;
friend void initializeUString();
friend bool operator==(const UString&, const UString&);
......@@ -255,7 +254,7 @@ namespace JSC {
int compare(const UString&, const UString&);
inline UString::UString()
: m_rep(&Rep::null())
: m_rep(s_nullRep)
{
}
......
......@@ -34,7 +34,44 @@ using namespace WTF::Unicode;
using namespace std;
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()
{
ASSERT((bufferOwnership() == BufferShared)
......
......@@ -92,15 +92,9 @@ public:
return &empty();
}
static PassRefPtr<UStringImpl> create(const UChar* buffer, int length)
{
UChar* newBuffer;
if (PassRefPtr<UStringImpl> impl = tryCreateUninitialized(length, newBuffer)) {
copyChars(newBuffer, buffer, length);
return impl;
}
return &null();
}
static PassRefPtr<UStringImpl> create(const char* c);
static PassRefPtr<UStringImpl> create(const char* c, int length);
static PassRefPtr<UStringImpl> create(const UChar* buffer, int length);
static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, int offset, int length)
{
......@@ -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) { return WTF::stringHash(s); }
static UStringImpl& null() { return *s_null; }
static UStringImpl& empty() { return *s_empty; }
ALWAYS_INLINE void checkConsistency() const
......@@ -288,7 +281,6 @@ private:
mutable unsigned m_isIdentifier : 1;
UntypedPtrAndBitfield m_dataBuffer;
JS_EXPORTDATA static UStringImpl* s_null;
JS_EXPORTDATA static UStringImpl* s_empty;
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