Bug 773519. Speed up string argument conversion in DOM bindings by faking an XPCOM string. r=peterv

This commit is contained in:
Boris Zbarsky 2012-07-17 12:18:53 -04:00
parent 3951284caf
commit ca83439a51
2 changed files with 89 additions and 5 deletions

View File

@ -682,6 +682,15 @@ public:
#endif
}
template<typename U>
void operator=(U* t) {
ptr = t->ToAStringPtr();
MOZ_ASSERT(ptr);
#ifdef DEBUG
inited = true;
#endif
}
T** Slot() {
#ifdef DEBUG
inited = true;
@ -736,6 +745,71 @@ protected:
#endif
};
// A struct that has the same layout as an nsDependentString but much
// faster constructor and destructor behavior
struct FakeDependentString {
FakeDependentString() :
mFlags(nsDependentString::F_TERMINATED)
{
}
void SetData(const nsDependentString::char_type* aData,
nsDependentString::size_type aLength) {
MOZ_ASSERT(mFlags == nsDependentString::F_TERMINATED);
mData = aData;
mLength = aLength;
}
void Truncate() {
mData = nsnull;
mLength = 0;
}
void SetNull() {
Truncate();
mFlags |= nsDependentString::F_VOIDED;
}
const nsAString* ToAStringPtr() const {
return reinterpret_cast<const nsDependentString*>(this);
}
nsAString* ToAStringPtr() {
return reinterpret_cast<nsDependentString*>(this);
}
operator const nsAString& () const {
return *reinterpret_cast<const nsDependentString*>(this);
}
private:
const nsDependentString::char_type* mData;
nsDependentString::size_type mLength;
PRUint32 mFlags;
// A class to use for our static asserts to ensure our object layout
// matches that of nsDependentString.
class DependentStringAsserter;
friend class DependentStringAsserter;
class DepedentStringAsserter : public nsDependentString {
public:
static void StaticAsserts() {
MOZ_STATIC_ASSERT(sizeof(FakeDependentString) == sizeof(nsDependentString),
"Must have right object size");
MOZ_STATIC_ASSERT(offsetof(FakeDependentString, mData) ==
offsetof(DepedentStringAsserter, mData),
"Offset of mData should match");
MOZ_STATIC_ASSERT(offsetof(FakeDependentString, mLength) ==
offsetof(DepedentStringAsserter, mLength),
"Offset of mLength should match");
MOZ_STATIC_ASSERT(offsetof(FakeDependentString, mFlags) ==
offsetof(DepedentStringAsserter, mFlags),
"Offset of mFlags should match");
}
};
};
enum StringificationBehavior {
eStringify,
eEmpty,
@ -746,7 +820,7 @@ static inline bool
ConvertJSValueToString(JSContext* cx, const JS::Value& v, JS::Value* pval,
StringificationBehavior nullBehavior,
StringificationBehavior undefinedBehavior,
nsDependentString& result)
FakeDependentString& result)
{
JSString *s;
if (v.isString()) {
@ -767,7 +841,11 @@ ConvertJSValueToString(JSContext* cx, const JS::Value& v, JS::Value* pval,
if (behavior != eStringify || !pval) {
// Here behavior == eStringify implies !pval, so both eNull and
// eStringify should end up with void strings.
result.SetIsVoid(behavior != eEmpty);
if (behavior == eEmpty) {
result.Truncate();
} else {
result.SetNull();
}
return true;
}
@ -784,7 +862,7 @@ ConvertJSValueToString(JSContext* cx, const JS::Value& v, JS::Value* pval,
return false;
}
result.Rebind(chars, len);
result.SetData(chars, len);
return true;
}
@ -839,6 +917,12 @@ public:
mPassed = true;
}
void operator=(const FakeDependentString* str) {
MOZ_ASSERT(str);
mStr = str->ToAStringPtr();
mPassed = true;
}
const nsAString& Value() const {
MOZ_ASSERT(WasPassed());
return *mStr;

View File

@ -1977,7 +1977,7 @@ for (uint32_t i = 0; i < length; ++i) {
declType = CGGeneric("nsString")
return (
"{\n"
" nsDependentString str;\n"
" FakeDependentString str;\n"
" if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, str)) {\n"
" return false;\n"
" }\n"
@ -1997,7 +1997,7 @@ for (uint32_t i = 0; i < length; ++i) {
"}\n"
"const_cast<%s&>(${declName}) = &${holderName};" %
(nullBehavior, undefinedBehavior, declType),
CGGeneric("const " + declType), CGGeneric("nsDependentString"),
CGGeneric("const " + declType), CGGeneric("FakeDependentString"),
# No need to deal with Optional here; we have handled it already
False)