[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.17-1283-gcf603cf
barraclough at apple.com
barraclough at apple.com
Tue Jan 5 23:46:52 UTC 2010
The following commit has been merged in the webkit-1.1 branch:
commit b439817ad9015df35a321f85c07e9787bc53975f
Author: barraclough at apple.com <barraclough at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Thu Dec 10 22:13:15 2009 +0000
https://bugs.webkit.org/show_bug.cgi?id=32367
Add support for short Ropes (up to 3 entries) inline within JSString.
(rather than externally allocating an object to hold the rope).
Switch jsAdd of (JSString* + JSString*) to now make use of Ropes.
Reviewed by Oliver Hunt & Mark Rowe.
~1% progression on Sunspidey.
* interpreter/Interpreter.cpp:
(JSC::Interpreter::privateExecute):
* jit/JITOpcodes.cpp:
(JSC::JIT::privateCompileCTIMachineTrampolines):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* runtime/JSString.cpp:
(JSC::JSString::resolveRope):
(JSC::JSString::toBoolean):
(JSC::JSString::getStringPropertyDescriptor):
* runtime/JSString.h:
(JSC::JSString::Rope::Fiber::deref):
(JSC::JSString::Rope::Fiber::ref):
(JSC::JSString::Rope::Fiber::refAndGetLength):
(JSC::JSString::Rope::append):
(JSC::JSString::JSString):
(JSC::JSString::~JSString):
(JSC::JSString::value):
(JSC::JSString::tryGetValue):
(JSC::JSString::length):
(JSC::JSString::canGetIndex):
(JSC::JSString::appendStringInConstruct):
(JSC::JSString::appendValueInConstructAndIncrementLength):
(JSC::JSString::isRope):
(JSC::JSString::string):
(JSC::JSString::ropeLength):
(JSC::JSString::getStringPropertySlot):
* runtime/Operations.h:
(JSC::jsString):
(JSC::jsAdd):
(JSC::resolveBase):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@51964 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 3d4d640..c678494 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,46 @@
+2009-12-10 Gavin Barraclough <barraclough at apple.com>
+
+ Reviewed by Oliver Hunt & Mark Rowe.
+
+ https://bugs.webkit.org/show_bug.cgi?id=32367
+ Add support for short Ropes (up to 3 entries) inline within JSString.
+ (rather than externally allocating an object to hold the rope).
+ Switch jsAdd of (JSString* + JSString*) to now make use of Ropes.
+
+ ~1% progression on Sunspidey.
+
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::privateCompileCTIMachineTrampolines):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * runtime/JSString.cpp:
+ (JSC::JSString::resolveRope):
+ (JSC::JSString::toBoolean):
+ (JSC::JSString::getStringPropertyDescriptor):
+ * runtime/JSString.h:
+ (JSC::JSString::Rope::Fiber::deref):
+ (JSC::JSString::Rope::Fiber::ref):
+ (JSC::JSString::Rope::Fiber::refAndGetLength):
+ (JSC::JSString::Rope::append):
+ (JSC::JSString::JSString):
+ (JSC::JSString::~JSString):
+ (JSC::JSString::value):
+ (JSC::JSString::tryGetValue):
+ (JSC::JSString::length):
+ (JSC::JSString::canGetIndex):
+ (JSC::JSString::appendStringInConstruct):
+ (JSC::JSString::appendValueInConstructAndIncrementLength):
+ (JSC::JSString::isRope):
+ (JSC::JSString::string):
+ (JSC::JSString::ropeLength):
+ (JSC::JSString::getStringPropertySlot):
+ * runtime/Operations.h:
+ (JSC::jsString):
+ (JSC::jsAdd):
+ (JSC::resolveBase):
+
2009-12-09 Anders Carlsson <andersca at apple.com>
Reviewed by Geoffrey Garen.
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index 4e1a56c..ed8bf5b 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -3530,7 +3530,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
int src = vPC[2].u.operand;
int count = vPC[3].u.operand;
- callFrame->r(dst) = concatenateStrings(callFrame, &callFrame->registers()[src], count);
+ callFrame->r(dst) = jsString(callFrame, &callFrame->registers()[src], count);
CHECK_FOR_EXCEPTION();
vPC += OPCODE_LENGTH(op_strcat);
diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp
index d7e7496..77fec28 100644
--- a/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/JavaScriptCore/jit/JITOpcodes.cpp
@@ -52,7 +52,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
// Checks out okay! - get the length from the Ustring.
- load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_length)), regT2);
+ load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_stringLength)), regT2);
Jump string_failureCases3 = branch32(Above, regT2, Imm32(INT_MAX));
move(regT2, regT0);
@@ -1636,7 +1636,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
// Checks out okay! - get the length from the Ustring.
- load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_length)), regT0);
+ load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_stringLength)), regT0);
Jump string_failureCases3 = branch32(Above, regT0, Imm32(JSImmediate::maxImmediateInt));
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index 418782f..fdf3d48 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -1043,25 +1043,9 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
bool leftIsString = v1.isString();
if (leftIsString && v2.isString()) {
- if (asString(v1)->isRope() || asString(v2)->isRope()) {
- RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(2);
- if (UNLIKELY(!rope)) {
- throwOutOfMemoryError(callFrame);
- VM_THROW_EXCEPTION();
- }
- rope->initializeFiber(0, asString(v1));
- rope->initializeFiber(1, asString(v2));
- JSGlobalData* globalData = &callFrame->globalData();
- return JSValue::encode(new (globalData) JSString(globalData, rope.release()));
- }
-
- RefPtr<UString::Rep> value = concatenate(asString(v1)->value(callFrame).rep(), asString(v2)->value(callFrame).rep());
- if (UNLIKELY(!value)) {
- throwOutOfMemoryError(callFrame);
- VM_THROW_EXCEPTION();
- }
-
- return JSValue::encode(jsString(stackFrame.globalData, value.release()));
+ JSValue result = jsString(callFrame, asString(v1), asString(v2));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
}
if (rightIsNumber & leftIsString) {
@@ -2851,7 +2835,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat)
{
STUB_INIT_STACK_FRAME(stackFrame);
- JSValue result = concatenateStrings(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
+ JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
CHECK_FOR_EXCEPTION_AT_END();
return JSValue::encode(result);
}
diff --git a/JavaScriptCore/runtime/JSString.cpp b/JavaScriptCore/runtime/JSString.cpp
index c668928..28ae6f7 100644
--- a/JavaScriptCore/runtime/JSString.cpp
+++ b/JavaScriptCore/runtime/JSString.cpp
@@ -96,30 +96,34 @@ void JSString::resolveRope(ExecState* exec) const
// Allocate the buffer to hold the final string, position initially points to the end.
UChar* buffer;
- if (!tryFastMalloc(m_length * sizeof(UChar)).getValue(buffer)) {
- m_rope.clear();
+ if (!tryFastMalloc(m_stringLength * sizeof(UChar)).getValue(buffer)) {
+ for (unsigned i = 0; i < m_ropeLength; ++i)
+ m_fibers[i].deref();
+ m_ropeLength = 0;
ASSERT(!isRope());
ASSERT(m_value == UString());
throwOutOfMemoryError(exec);
return;
}
- UChar* position = buffer + m_length;
+ UChar* position = buffer + m_stringLength;
// Start with the current Rope.
Vector<Rope::Fiber, 32> workQueue;
- Rope* rope = m_rope.get();
+ Rope::Fiber currentFiber;
+ for (unsigned i = 0; i < (m_ropeLength - 1); ++i)
+ workQueue.append(m_fibers[i]);
+ currentFiber = m_fibers[m_ropeLength - 1];
while (true) {
- // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber'
- // (we will be working backwards over the rope).
- unsigned ropeLengthMinusOne = rope->ropeLength() - 1;
- for (unsigned i = 0; i < ropeLengthMinusOne; ++i)
- workQueue.append(rope->fibers(i));
- Rope::Fiber currentFiber = rope->fibers(ropeLengthMinusOne);
-
- // Spin backwards over the workQueue (starting with currentFiber),
- // writing the strings into the buffer.
- while (currentFiber.isString()) {
+ if (currentFiber.isRope()) {
+ Rope* rope = currentFiber.rope();
+ // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber'
+ // (we will be working backwards over the rope).
+ unsigned ropeLengthMinusOne = rope->ropeLength() - 1;
+ for (unsigned i = 0; i < ropeLengthMinusOne; ++i)
+ workQueue.append(rope->fibers(i));
+ currentFiber = rope->fibers(ropeLengthMinusOne);
+ } else {
UString::Rep* string = currentFiber.string();
unsigned length = string->len;
position -= length;
@@ -129,8 +133,10 @@ void JSString::resolveRope(ExecState* exec) const
if (workQueue.isEmpty()) {
// Create a string from the UChar buffer, clear the rope RefPtr.
ASSERT(buffer == position);
- m_value = UString(buffer, m_length, false);
- m_rope.clear();
+ m_value = UString::Rep::create(buffer, m_stringLength);
+ for (unsigned i = 0; i < m_ropeLength; ++i)
+ m_fibers[i].deref();
+ m_ropeLength = 0;
ASSERT(!isRope());
return;
@@ -140,11 +146,6 @@ void JSString::resolveRope(ExecState* exec) const
currentFiber = workQueue.last();
workQueue.removeLast();
}
-
- // If we get here we fell out of the loop concatenating strings - currentFiber is a rope.
- // set the 'rope' variable, and continue around the loop.
- ASSERT(currentFiber.isRope());
- rope = currentFiber.rope();
}
}
@@ -162,7 +163,7 @@ bool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& resu
bool JSString::toBoolean(ExecState*) const
{
- return m_length;
+ return m_stringLength;
}
double JSString::toNumber(ExecState* exec) const
@@ -224,13 +225,13 @@ bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNam
bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
if (propertyName == exec->propertyNames().length) {
- descriptor.setDescriptor(jsNumber(exec, m_length), DontEnum | DontDelete | ReadOnly);
+ descriptor.setDescriptor(jsNumber(exec, m_stringLength), DontEnum | DontDelete | ReadOnly);
return true;
}
bool isStrictUInt32;
unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
- if (isStrictUInt32 && i < m_length) {
+ if (isStrictUInt32 && i < m_stringLength) {
descriptor.setDescriptor(jsSingleCharacterSubstring(exec, value(exec), i), DontDelete | ReadOnly);
return true;
}
diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h
index 633dd98..93b11f1 100644
--- a/JavaScriptCore/runtime/JSString.h
+++ b/JavaScriptCore/runtime/JSString.h
@@ -75,6 +75,35 @@ namespace JSC {
Fiber(UString::Rep* string) : m_value(reinterpret_cast<intptr_t>(string)) {}
Fiber(Rope* rope) : m_value(reinterpret_cast<intptr_t>(rope) | 1) {}
+ void deref()
+ {
+ if (isRope())
+ rope()->deref();
+ else
+ string()->deref();
+ }
+
+ Fiber& ref()
+ {
+ if (isString())
+ string()->ref();
+ else
+ rope()->ref();
+ return *this;
+ }
+
+ unsigned refAndGetLength()
+ {
+ if (isString()) {
+ UString::Rep* rep = string();
+ return rep->ref()->len;
+ } else {
+ Rope* r = rope();
+ r->ref();
+ return r->stringLength();
+ }
+ }
+
bool isRope() { return m_value & 1; }
Rope* rope() { return reinterpret_cast<Rope*>(m_value & ~1); }
bool isString() { return !isRope(); }
@@ -97,25 +126,24 @@ namespace JSC {
~Rope();
void destructNonRecursive();
- void initializeFiber(unsigned index, const UString& string)
+ void append(unsigned &index, Fiber& fiber)
{
- UString::Rep* rep = string.rep();
- rep->ref();
- m_fibers[index] = Fiber(rep);
- m_stringLength += rep->len;
+ m_fibers[index++] = fiber;
+ m_stringLength += fiber.refAndGetLength();
}
- void initializeFiber(unsigned index, Rope* rope)
+ void append(unsigned &index, const UString& string)
{
- rope->ref();
- m_fibers[index] = Fiber(rope);
- m_stringLength += rope->stringLength();
+ UString::Rep* rep = string.rep();
+ m_fibers[index++] = Fiber(rep);
+ m_stringLength += rep->ref()->len;
}
- void initializeFiber(unsigned index, JSString* jsString)
+ void append(unsigned& index, JSString* jsString)
{
- if (jsString->isRope())
- initializeFiber(index, jsString->rope());
- else
- initializeFiber(index, jsString->string());
+ if (jsString->isRope()) {
+ for (unsigned i = 0; i < jsString->m_ropeLength; ++i)
+ append(index, jsString->m_fibers[i]);
+ } else
+ append(index, jsString->string());
}
unsigned ropeLength() { return m_ropeLength; }
@@ -133,8 +161,9 @@ namespace JSC {
JSString(JSGlobalData* globalData, const UString& value)
: JSCell(globalData->stringStructure.get())
- , m_length(value.size())
+ , m_stringLength(value.size())
, m_value(value)
+ , m_ropeLength(0)
{
Heap::heap(this)->reportExtraMemoryCost(value.cost());
}
@@ -142,46 +171,79 @@ namespace JSC {
enum HasOtherOwnerType { HasOtherOwner };
JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
: JSCell(globalData->stringStructure.get())
- , m_length(value.size())
+ , m_stringLength(value.size())
, m_value(value)
+ , m_ropeLength(0)
{
}
JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType)
: JSCell(globalData->stringStructure.get())
- , m_length(value->size())
+ , m_stringLength(value->size())
, m_value(value)
+ , m_ropeLength(0)
{
}
JSString(JSGlobalData* globalData, PassRefPtr<JSString::Rope> rope)
: JSCell(globalData->stringStructure.get())
- , m_length(rope->stringLength())
- , m_rope(rope)
+ , m_stringLength(rope->stringLength())
+ , m_ropeLength(1)
{
+ m_fibers[0] = rope.releaseRef();
+ }
+ // This constructor constructs a new string by concatenating s1 & s2.
+ // This should only be called with ropeLength <= 3.
+ JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, JSString* s2)
+ : JSCell(globalData->stringStructure.get())
+ , m_stringLength(s1->length() + s2->length())
+ , m_ropeLength(ropeLength)
+ {
+ ASSERT(ropeLength <= s_maxInternalRopeLength);
+ unsigned index = 0;
+ appendStringInConstruct(index, s1);
+ appendStringInConstruct(index, s2);
+ ASSERT(ropeLength == index);
+ }
+ // This constructor constructs a new string by concatenating v1, v2 & v3.
+ // This should only be called with ropeLength <= 3 ... which since every
+ // value must require a ropeLength of at least one implies that the length
+ // for each value must be exactly 1!
+ JSString(ExecState* exec, JSValue v1, JSValue v2, JSValue v3)
+ : JSCell(exec->globalData().stringStructure.get())
+ , m_stringLength(0)
+ , m_ropeLength(s_maxInternalRopeLength)
+ {
+ unsigned index = 0;
+ appendValueInConstructAndIncrementLength(exec, index, v1);
+ appendValueInConstructAndIncrementLength(exec, index, v2);
+ appendValueInConstructAndIncrementLength(exec, index, v3);
+ ASSERT(index == s_maxInternalRopeLength);
+ }
+
+ ~JSString()
+ {
+ for (unsigned i = 0; i < m_ropeLength; ++i)
+ m_fibers[i].deref();
}
const UString& value(ExecState* exec) const
{
- if (m_rope)
+ if (isRope())
resolveRope(exec);
return m_value;
}
const UString tryGetValue() const
{
- if (m_rope)
+ if (isRope())
UString();
return m_value;
}
- unsigned length() { return m_length; }
-
- bool isRope() const { return m_rope; }
- Rope* rope() { ASSERT(isRope()); return m_rope.get(); }
- UString& string() { ASSERT(!isRope()); return m_value; }
+ unsigned length() { return m_stringLength; }
bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
- bool canGetIndex(unsigned i) { return i < m_length; }
+ bool canGetIndex(unsigned i) { return i < m_stringLength; }
JSString* getIndex(ExecState*, unsigned);
static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion)); }
@@ -190,11 +252,36 @@ namespace JSC {
enum VPtrStealingHackType { VPtrStealingHack };
JSString(VPtrStealingHackType)
: JSCell(0)
+ , m_ropeLength(0)
{
}
void resolveRope(ExecState*) const;
+ void appendStringInConstruct(unsigned& index, JSString* jsString)
+ {
+ if (jsString->isRope()) {
+ for (unsigned i = 0; i < jsString->m_ropeLength; ++i)
+ m_fibers[index++] = jsString->m_fibers[i].ref();
+ } else
+ m_fibers[index++] = Rope::Fiber(jsString->string().rep()->ref());
+ }
+
+ void appendValueInConstructAndIncrementLength(ExecState* exec, unsigned& index, JSValue v)
+ {
+ if (v.isString()) {
+ ASSERT(asCell(v)->isString());
+ JSString* s = static_cast<JSString*>(asCell(v));
+ ASSERT(s->ropeLength() == 1);
+ appendStringInConstruct(index, s);
+ m_stringLength += s->length();
+ } else {
+ UString u(v.toString(exec));
+ m_fibers[index++] = Rope::Fiber(u.rep()->ref());
+ m_stringLength += u.size();
+ }
+ }
+
virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
virtual bool toBoolean(ExecState*) const;
@@ -211,10 +298,20 @@ namespace JSC {
virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+ static const unsigned s_maxInternalRopeLength = 3;
+
// A string is represented either by a UString or a Rope.
- unsigned m_length;
+ unsigned m_stringLength;
mutable UString m_value;
- mutable RefPtr<Rope> m_rope;
+ mutable unsigned m_ropeLength;
+ mutable Rope::Fiber m_fibers[s_maxInternalRopeLength];
+
+ bool isRope() const { return m_ropeLength; }
+ UString& string() { ASSERT(!isRope()); return m_value; }
+ unsigned ropeLength() { return m_ropeLength ? m_ropeLength : 1; }
+
+ friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2);
+ friend JSValue jsString(ExecState* exec, Register* strings, unsigned count);
};
JSString* asString(JSValue);
@@ -278,7 +375,7 @@ namespace JSC {
}
return new (globalData) JSString(globalData, s);
}
-
+
inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
{
ASSERT(offset <= static_cast<unsigned>(s.size()));
@@ -319,13 +416,13 @@ namespace JSC {
ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
if (propertyName == exec->propertyNames().length) {
- slot.setValue(jsNumber(exec, m_length));
+ slot.setValue(jsNumber(exec, m_stringLength));
return true;
}
bool isStrictUInt32;
unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
- if (isStrictUInt32 && i < m_length) {
+ if (isStrictUInt32 && i < m_stringLength) {
slot.setValue(jsSingleCharacterSubstring(exec, value(exec), i));
return true;
}
@@ -335,7 +432,7 @@ namespace JSC {
ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
{
- if (propertyName < m_length) {
+ if (propertyName < m_stringLength) {
slot.setValue(jsSingleCharacterSubstring(exec, value(exec), propertyName));
return true;
}
diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h
index 035adc9..1cab06d 100644
--- a/JavaScriptCore/runtime/Operations.h
+++ b/JavaScriptCore/runtime/Operations.h
@@ -35,6 +35,58 @@ namespace JSC {
bool jsIsObjectType(JSValue);
bool jsIsFunctionType(JSValue);
+ ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
+ {
+ unsigned ropeLength = s1->ropeLength() + s2->ropeLength();
+ JSGlobalData* globalData = &exec->globalData();
+
+ if (ropeLength <= JSString::s_maxInternalRopeLength)
+ return new (globalData) JSString(globalData, ropeLength, s1, s2);
+
+ unsigned index = 0;
+ RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
+ if (UNLIKELY(!rope))
+ return throwOutOfMemoryError(exec);
+ rope->append(index, s1);
+ rope->append(index, s2);
+ ASSERT(index == ropeLength);
+ return new (globalData) JSString(globalData, rope.release());
+ }
+
+ ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count)
+ {
+ ASSERT(count >= 3);
+
+ unsigned ropeLength = 0;
+ for (unsigned i = 0; i < count; ++i) {
+ JSValue v = strings[i].jsValue();
+ if (LIKELY(v.isString()))
+ ropeLength += asString(v)->ropeLength();
+ else
+ ++ropeLength;
+ }
+
+ JSGlobalData* globalData = &exec->globalData();
+ if (ropeLength == 3)
+ return new (globalData) JSString(exec, strings[0].jsValue(), strings[1].jsValue(), strings[2].jsValue());
+
+ RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
+ if (UNLIKELY(!rope))
+ return throwOutOfMemoryError(exec);
+
+ unsigned index = 0;
+ for (unsigned i = 0; i < count; ++i) {
+ JSValue v = strings[i].jsValue();
+ if (LIKELY(v.isString()))
+ rope->append(index, asString(v));
+ else
+ rope->append(index, v.toString(exec));
+ }
+
+ ASSERT(index == ropeLength);
+ return new (globalData) JSString(globalData, rope.release());
+ }
+
// ECMA 11.9.3
inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2)
{
@@ -204,20 +256,11 @@ namespace JSC {
bool leftIsString = v1.isString();
if (leftIsString && v2.isString()) {
- if (asString(v1)->isRope() || asString(v2)->isRope()) {
- RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(2);
- if (UNLIKELY(!rope))
- return throwOutOfMemoryError(callFrame);
- rope->initializeFiber(0, asString(v1));
- rope->initializeFiber(1, asString(v2));
- JSGlobalData* globalData = &callFrame->globalData();
- return new (globalData) JSString(globalData, rope.release());
- }
-
- RefPtr<UString::Rep> value = concatenate(asString(v1)->value(callFrame).rep(), asString(v2)->value(callFrame).rep());
- if (!value)
- return throwOutOfMemoryError(callFrame);
- return jsString(callFrame, value.release());
+ if (!asString(v1)->length())
+ return asString(v2);
+ if (!asString(v2)->length())
+ return asString(v1);
+ return jsString(callFrame, asString(v1), asString(v2));
}
if (rightIsNumber & leftIsString) {
@@ -303,26 +346,6 @@ namespace JSC {
ASSERT_NOT_REACHED();
return JSValue();
}
-
- ALWAYS_INLINE JSValue concatenateStrings(CallFrame* callFrame, Register* strings, unsigned count)
- {
- ASSERT(count >= 3);
-
- RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(count);
- if (UNLIKELY(!rope))
- return throwOutOfMemoryError(callFrame);
-
- for (unsigned i = 0; i < count; ++i) {
- JSValue v = strings[i].jsValue();
- if (LIKELY(v.isString()))
- rope->initializeFiber(i, asString(v));
- else
- rope->initializeFiber(i, v.toString(callFrame));
- }
-
- JSGlobalData* globalData = &callFrame->globalData();
- return new (globalData) JSString(globalData, rope.release());
- }
} // namespace JSC
#endif // Operations_h
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list