Bug 676700 - Slightly speed up js::IndexToId by converting directly to atom, not to string and then to atom. r=luke

--HG--
extra : rebase_source : d352929e4002f285670448e4515bea404f2cf88f
This commit is contained in:
Jeff Walden 2011-08-04 19:21:25 -07:00
parent 30dcca107a
commit f0a15f8ce0
3 changed files with 76 additions and 51 deletions

View File

@ -42,6 +42,9 @@
*/
#include <stdlib.h>
#include <string.h>
#include "mozilla/RangedPtr.h"
#include "jstypes.h"
#include "jsstdint.h"
#include "jsutil.h"
@ -665,6 +668,27 @@ js_InitAtomMap(JSContext *cx, JSAtomMap *map, AtomIndexMap *indices)
}
}
namespace js {
bool
IndexToIdSlow(JSContext *cx, uint32 index, jsid *idp)
{
JS_ASSERT(index > JSID_INT_MAX);
jschar buf[UINT32_CHAR_BUFFER_LENGTH];
RangedPtr<jschar> end(buf + JS_ARRAY_LENGTH(buf), buf, buf + JS_ARRAY_LENGTH(buf));
RangedPtr<jschar> start = BackfillIndexInCharBuffer(index, end);
JSAtom *atom = js_AtomizeChars(cx, start.get(), end - start);
if (!atom)
return false;
*idp = ATOM_TO_JSID(atom);
JS_ASSERT(js_CheckForStringIndex(*idp) == *idp);
return true;
}
} /* namespace js */
/* JSBOXEDWORD_INT_MAX as a string */
#define JSBOXEDWORD_INT_MAX_STRING "1073741823"

View File

@ -40,6 +40,8 @@
#ifndef jsatominlines_h___
#define jsatominlines_h___
#include "mozilla/RangedPtr.h"
#include "jsatom.h"
#include "jsnum.h"
#include "jsobj.h"
@ -133,6 +135,37 @@ js_Int32ToId(JSContext* cx, int32 index, jsid* id)
namespace js {
static const size_t UINT32_CHAR_BUFFER_LENGTH = sizeof("4294967295") - 1;
/*
* Write out character representing |index| to the memory just before |end|.
* Thus |*end| is not touched, but |end[-1]| and earlier are modified as
* appropriate. There must be at least UINT32_CHAR_BUFFER_LENGTH elements
* before |end| to avoid buffer underflow. The start of the characters written
* is returned and is necessarily before |end|.
*/
template <typename T>
inline mozilla::RangedPtr<T>
BackfillIndexInCharBuffer(uint32 index, mozilla::RangedPtr<T> end)
{
#ifdef DEBUG
/*
* Assert that the buffer we're filling will hold as many characters as we
* could write out, by dereferencing the index that would hold the most
* significant digit.
*/
(void) *(end - UINT32_CHAR_BUFFER_LENGTH);
#endif
do {
uint32 next = index / 10, digit = index % 10;
*--end = '0' + digit;
index = next;
} while (index > 0);
return end;
}
inline bool
IndexToId(JSContext *cx, uint32 index, jsid *idp)
{
@ -141,15 +174,8 @@ IndexToId(JSContext *cx, uint32 index, jsid *idp)
return true;
}
JSString *str = js_NumberToString(cx, index);
if (!str)
return false;
JSAtom *atom = js_AtomizeString(cx, str);
if (!atom)
return false;
*idp = ATOM_TO_JSID(atom);
return true;
extern bool IndexToIdSlow(JSContext *cx, uint32 index, jsid *idp);
return IndexToIdSlow(cx, index, idp);
}
static JS_ALWAYS_INLINE JSString *

View File

@ -75,6 +75,7 @@
#include "jsvector.h"
#include "jslibmath.h"
#include "jsatominlines.h"
#include "jsinterpinlines.h"
#include "jsnuminlines.h"
#include "jsobjinlines.h"
@ -650,23 +651,17 @@ js_IntToString(JSContext *cx, int32 si)
if (!str)
return NULL;
/* +1, since MAX_LENGTH does not count the null char. */
JS_STATIC_ASSERT(JSShortString::MAX_LENGTH + 1 >= sizeof("-2147483648"));
jschar *storage = str->inlineStorageBeforeInit();
RangedPtr<jschar> end(storage + JSShortString::MAX_SHORT_LENGTH,
storage, JSShortString::MAX_SHORT_LENGTH + 1);
*end = '\0';
jschar *end = str->inlineStorageBeforeInit() + JSShortString::MAX_SHORT_LENGTH;
jschar *cp = end;
*cp = 0;
do {
jsuint newui = ui / 10, digit = ui % 10; /* optimizers are our friends */
*--cp = '0' + digit;
ui = newui;
} while (ui != 0);
RangedPtr<jschar> start = BackfillIndexInCharBuffer(ui, end);
if (si < 0)
*--cp = '-';
*--start = '-';
str->initAtOffsetInBuffer(cp, end - cp);
str->initAtOffsetInBuffer(start.get(), end - start);
c->dtoaCache.cache(10, si, str);
return str;
@ -676,25 +671,15 @@ js_IntToString(JSContext *cx, int32 si)
static char *
IntToCString(ToCStringBuf *cbuf, jsint i, jsint base = 10)
{
char *cp;
jsuint u;
jsuint u = (i < 0) ? -i : i;
u = (i < 0) ? -i : i;
RangedPtr<char> cp(cbuf->sbuf + cbuf->sbufSize - 1, cbuf->sbuf, cbuf->sbufSize);
*cp = '\0';
cp = cbuf->sbuf + cbuf->sbufSize; /* one past last buffer cell */
*--cp = '\0'; /* null terminate the string to be */
/*
* Build the string from behind. We use multiply and subtraction
* instead of modulus because that's much faster.
*/
/* Build the string from behind. */
switch (base) {
case 10:
do {
jsuint newu = u / 10;
*--cp = (char)(u - newu * 10) + '0';
u = newu;
} while (u != 0);
cp = BackfillIndexInCharBuffer(u, cp);
break;
case 16:
do {
@ -715,8 +700,7 @@ IntToCString(ToCStringBuf *cbuf, jsint i, jsint base = 10)
if (i < 0)
*--cp = '-';
JS_ASSERT(cp >= cbuf->sbuf);
return cp;
return cp.get();
}
static JSString * JS_FASTCALL
@ -1282,23 +1266,14 @@ IndexToString(JSContext *cx, uint32 index)
if (!str)
return NULL;
/* +1, since MAX_LENGTH does not count the null char. */
JS_STATIC_ASSERT(JSShortString::MAX_LENGTH + 1 >= sizeof("4294967295"));
jschar *storage = str->inlineStorageBeforeInit();
size_t length = JSShortString::MAX_SHORT_LENGTH;
const RangedPtr<jschar> end(storage + length, storage, length + 1);
RangedPtr<jschar> cp = end;
*cp = '\0';
*end = '\0';
uint32 u = index;
do {
uint32 newu = u / 10, digit = u % 10;
*--cp = '0' + digit;
u = newu;
} while (u > 0);
RangedPtr<jschar> start = BackfillIndexInCharBuffer(index, end);
str->initAtOffsetInBuffer(cp.get(), end - cp);
str->initAtOffsetInBuffer(start.get(), end - start);
c->dtoaCache.cache(10, index, str);
return str;