Bug 676739 - Part 1: Suppress unnecessary temporary strings in js::ToAtom. r=luke

This commit is contained in:
Yaron Tausky
2013-08-27 11:17:41 +02:00
parent 0913514adb
commit 985a6b0665
4 changed files with 188 additions and 44 deletions

View File

@@ -24,6 +24,7 @@
#include "jscntxtinlines.h"
#include "jscompartmentinlines.h"
#include "jsobjinlines.h"
#include "vm/String-inl.h"
@@ -225,17 +226,12 @@ AtomIsInterned(JSContext *cx, JSAtom *atom)
return p->isTagged();
}
enum OwnCharsBehavior
{
CopyChars, /* in other words, do not take ownership */
TakeCharOwnership
};
/*
* When the jschars reside in a freshly allocated buffer the memory can be used
* as a new JSAtom's storage without copying. The contract is that the caller no
* longer owns the memory and this method is responsible for freeing the memory.
*/
template <AllowGC allowGC>
JS_ALWAYS_INLINE
static JSAtom *
AtomizeAndTakeOwnership(ExclusiveContext *cx, jschar *tbchars, size_t length, InternBehavior ib)
@@ -267,7 +263,7 @@ AtomizeAndTakeOwnership(ExclusiveContext *cx, jschar *tbchars, size_t length, In
AutoCompartment ac(cx, cx->atomsCompartment());
JSFlatString *flat = js_NewString<CanGC>(cx, tbchars, length);
JSFlatString *flat = js_NewString<allowGC>(cx, tbchars, length);
if (!flat) {
js_free(tbchars);
return NULL;
@@ -374,8 +370,9 @@ js::AtomizeString<CanGC>(ExclusiveContext *cx, JSString *str, InternBehavior ib)
template JSAtom *
js::AtomizeString<NoGC>(ExclusiveContext *cx, JSString *str, InternBehavior ib);
template <AllowGC allowGC>
JSAtom *
js::Atomize(ExclusiveContext *cx, const char *bytes, size_t length, InternBehavior ib)
js::AtomizeMaybeGC(ExclusiveContext *cx, const char *bytes, size_t length, InternBehavior ib)
{
CHECK_REQUEST(cx);
@@ -398,13 +395,27 @@ js::Atomize(ExclusiveContext *cx, const char *bytes, size_t length, InternBehavi
{
return NULL;
}
return AtomizeAndCopyChars<CanGC>(cx, inflated, inflatedLength, ib);
return AtomizeAndCopyChars<allowGC>(cx, inflated, inflatedLength, ib);
}
jschar *tbcharsZ = InflateString(cx, bytes, &length);
if (!tbcharsZ)
return NULL;
return AtomizeAndTakeOwnership(cx, tbcharsZ, length, ib);
return AtomizeAndTakeOwnership<allowGC>(cx, tbcharsZ, length, ib);
}
template JSAtom *
js::AtomizeMaybeGC<CanGC>(ExclusiveContext *cx, const char *bytes, size_t length,
InternBehavior ib);
template JSAtom *
js::AtomizeMaybeGC<NoGC>(ExclusiveContext *cx, const char *bytes, size_t length,
InternBehavior ib);
JSAtom *
js::Atomize(ExclusiveContext *cx, const char *bytes, size_t length, InternBehavior ib)
{
return AtomizeMaybeGC<CanGC>(cx, bytes, length, ib);
}
template <AllowGC allowGC>
@@ -452,17 +463,41 @@ js::IndexToIdSlow<CanGC>(ExclusiveContext *cx, uint32_t index, MutableHandleId i
template bool
js::IndexToIdSlow<NoGC>(ExclusiveContext *cx, uint32_t index, FakeMutableHandle<jsid> idp);
template <AllowGC allowGC>
static JSAtom *
ToAtomSlow(ExclusiveContext *cx, typename MaybeRooted<Value, allowGC>::HandleType arg)
{
JS_ASSERT(!arg.isString());
Value v = arg;
if (!v.isPrimitive()) {
if (!cx->shouldBeJSContext() || !allowGC)
return NULL;
RootedValue v2(cx, v);
if (!ToPrimitive(cx->asJSContext(), JSTYPE_STRING, &v2))
return NULL;
v = v2;
}
if (v.isString())
return AtomizeString<allowGC>(cx, v.toString());
if (v.isInt32())
return Int32ToAtom<allowGC>(cx, v.toInt32());
if (v.isDouble())
return NumberToAtom<allowGC>(cx, v.toDouble());
if (v.isBoolean())
return v.toBoolean() ? cx->names().true_ : cx->names().false_;
if (v.isNull())
return cx->names().null;
return cx->names().undefined;
}
template <AllowGC allowGC>
JSAtom *
js::ToAtom(ExclusiveContext *cx, typename MaybeRooted<Value, allowGC>::HandleType v)
{
if (!v.isString()) {
JSString *str = js::ToStringSlow<allowGC>(cx, v);
if (!str)
return NULL;
JS::Anchor<JSString *> anchor(str);
return AtomizeString<allowGC>(cx, str);
}
if (!v.isString())
return ToAtomSlow<allowGC>(cx, v);
JSString *str = v.toString();
if (str->isAtom())