Bug 503952 - Use JSTempVector in scanner/parser; remove JSStringBuffer (r=brendan)

This commit is contained in:
Luke Wagner 2009-08-14 16:10:59 -07:00
Родитель 6ae5b0ea2d
Коммит 81528e533d
12 изменённых файлов: 233 добавлений и 476 удалений

Просмотреть файл

@ -5490,7 +5490,7 @@ JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
JSCharBuffer cb(cx);
if (!js_Stringify(cx, vp, replacer, space, cb))
return false;
return callback(cb.begin(), cb.size(), data);
return callback(cb.begin(), cb.length(), data);
}
JS_PUBLIC_API(JSBool)

Просмотреть файл

@ -2096,7 +2096,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
const char *filename;
JSBool ok;
JSString *str, *arg;
JSTokenStream ts;
JSTokenStream ts(cx);
JSPrincipals *principals;
jschar *collected_args, *cp;
void *mark;
@ -2232,8 +2232,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
/* Initialize a tokenstream that reads from the given string. */
if (!js_InitTokenStream(cx, &ts, collected_args, args_length,
NULL, filename, lineno)) {
if (!ts.init(cx, collected_args, args_length, NULL, filename, lineno)) {
JS_ARENA_RELEASE(&cx->tempPool, mark);
return JS_FALSE;
}
@ -2296,7 +2295,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_FORMAL);
}
js_CloseTokenStream(cx, &ts);
ts.close(cx);
JS_ARENA_RELEASE(&cx->tempPool, mark);
if (state != OK)
return JS_FALSE;

Просмотреть файл

@ -887,7 +887,7 @@ js_NumberValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb)
*/
size_t cstrlen = strlen(cstr);
JS_ASSERT(cstrlen < arrSize);
size_t sizeBefore = cb.size();
size_t sizeBefore = cb.length();
if (!cb.growBy(cstrlen))
return JS_FALSE;
jschar *appendBegin = cb.begin() + sizeBefore;

Просмотреть файл

@ -807,7 +807,7 @@ PushValue(JSContext *cx, JSONParser *jp, JSObject *parent, jsval value)
}
} else {
ok = JS_DefineUCProperty(cx, parent, jp->objectKey.begin(),
jp->objectKey.size(), value,
jp->objectKey.length(), value,
NULL, NULL, JSPROP_ENUMERATE);
jp->objectKey.clear();
}
@ -982,7 +982,7 @@ HandleData(JSContext *cx, JSONParser *jp, JSONDataType type)
switch (type) {
case JSON_DATA_STRING:
ok = HandleString(cx, jp, jp->buffer.begin(), jp->buffer.size());
ok = HandleString(cx, jp, jp->buffer.begin(), jp->buffer.length());
break;
case JSON_DATA_KEYSTRING:
@ -990,12 +990,12 @@ HandleData(JSContext *cx, JSONParser *jp, JSONDataType type)
break;
case JSON_DATA_NUMBER:
ok = HandleNumber(cx, jp, jp->buffer.begin(), jp->buffer.size());
ok = HandleNumber(cx, jp, jp->buffer.begin(), jp->buffer.length());
break;
default:
JS_ASSERT(type == JSON_DATA_KEYWORD);
ok = HandleKeyword(cx, jp, jp->buffer.begin(), jp->buffer.size());
ok = HandleKeyword(cx, jp, jp->buffer.begin(), jp->buffer.length());
break;
}

Просмотреть файл

@ -78,6 +78,7 @@
#include "jsstr.h"
#include "jsstaticcheck.h"
#include "jslibmath.h"
#include "jsvector.h"
#if JS_HAS_XML_SUPPORT
#include "jsxml.h"
@ -211,7 +212,7 @@ JSCompiler::init(const jschar *base, size_t length,
JSContext *cx = context;
tempPoolMark = JS_ARENA_MARK(&cx->tempPool);
if (!js_InitTokenStream(cx, TS(this), base, length, fp, filename, lineno)) {
if (!tokenStream.init(cx, base, length, fp, filename, lineno)) {
JS_ARENA_RELEASE(&cx->tempPool, tempPoolMark);
return false;
}
@ -231,7 +232,7 @@ JSCompiler::~JSCompiler()
JS_ASSERT(tempRoot.u.compiler == this);
JS_POP_TEMP_ROOT(cx, &tempRoot);
JS_UNKEEP_ATOMS(cx->runtime);
js_CloseTokenStream(cx, TS(this));
tokenStream.close(cx);
JS_ARENA_RELEASE(&cx->tempPool, tempPoolMark);
}
@ -8206,11 +8207,9 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
if (!pn)
return NULL;
/* Token stream ensures that tokenbuf is NUL-terminated. */
JS_ASSERT(*ts->tokenbuf.ptr == (jschar) 0);
obj = js_NewRegExpObject(cx, ts,
ts->tokenbuf.base,
ts->tokenbuf.ptr - ts->tokenbuf.base,
ts->tokenbuf.begin(),
ts->tokenbuf.length(),
CURRENT_TOKEN(ts).t_reflags);
if (!obj)
return NULL;

Просмотреть файл

@ -822,8 +822,8 @@ struct JSCompiler {
JSTempValueRooter tempRoot; /* root to trace traceListHead */
JSCompiler(JSContext *cx, JSPrincipals *prin = NULL, JSStackFrame *cfp = NULL)
: context(cx), aleFreeList(NULL), principals(NULL), callerFrame(cfp),
nodeList(NULL), functionCount(0), traceListHead(NULL)
: context(cx), aleFreeList(NULL), tokenStream(cx), principals(NULL),
callerFrame(cfp), nodeList(NULL), functionCount(0), traceListHead(NULL)
{
memset(tempFreeList, 0, sizeof tempFreeList);
setPrincipals(prin);
@ -833,7 +833,7 @@ struct JSCompiler {
~JSCompiler();
/*
* Initialize a compiler. Parameters are passed on to js_InitTokenStream.
* Initialize a compiler. Parameters are passed on to init tokenStream.
* The compiler owns the arena pool "tops-of-stack" space above the current
* JSContext.tempPool mark. This means you cannot allocate from tempPool
* and save the pointer beyond the next JSCompiler destructor invocation.

Просмотреть файл

@ -127,7 +127,6 @@ typedef struct JSScope JSScope;
typedef struct JSScopeOps JSScopeOps;
typedef struct JSScopeProperty JSScopeProperty;
typedef struct JSStackHeader JSStackHeader;
typedef struct JSStringBuffer JSStringBuffer;
typedef struct JSSubString JSSubString;
typedef struct JSTraceableNative JSTraceableNative;
typedef struct JSXML JSXML;

Просмотреть файл

@ -2291,7 +2291,7 @@ class RegExpNativeCompiler {
void targetCurrentPoint(LInsList &fails)
{
LIns *fail = lir->ins0(LIR_label);
for (size_t i = 0; i < fails.size(); ++i) {
for (size_t i = 0; i < fails.length(); ++i) {
fails[i]->setTarget(fail);
}
fails.clear();

Просмотреть файл

@ -71,6 +71,7 @@
#include "jsscan.h"
#include "jsscript.h"
#include "jsstaticcheck.h"
#include "jsvector.h"
#if JS_HAS_XML_SUPPORT
#include "jsxml.h"
@ -175,50 +176,15 @@ js_IsIdentifier(JSString *str)
return JS_TRUE;
}
#define TBMIN 64
/* Initialize members that aren't initialized in |init|. */
JSTokenStream::JSTokenStream(JSContext *cx)
: tokens(), cursor(), lookahead(), ungetpos(), ungetbuf(), flags(), linelen(),
linepos(), file(), listenerTSData(), saveEOL(), tokenbuf(cx)
{}
static JSBool
GrowTokenBuf(JSStringBuffer *sb, size_t newlength)
{
JSContext *cx;
jschar *base;
ptrdiff_t offset, length;
size_t tbsize;
JSArenaPool *pool;
cx = (JSContext*) sb->data;
base = sb->base;
offset = sb->ptr - base;
pool = &cx->tempPool;
if (!base) {
tbsize = TBMIN * sizeof(jschar);
length = TBMIN - 1;
JS_ARENA_ALLOCATE_CAST(base, jschar *, pool, tbsize);
} else {
length = sb->limit - base;
if ((size_t)length >= ~(size_t)0 / sizeof(jschar)) {
base = NULL;
} else {
tbsize = (length + 1) * sizeof(jschar);
length += length + 1;
JS_ARENA_GROW_CAST(base, jschar *, pool, tbsize, tbsize);
}
}
if (!base) {
js_ReportOutOfScriptQuota(cx);
sb->base = STRING_BUFFER_ERROR_BASE;
return JS_FALSE;
}
sb->base = base;
sb->limit = base + length;
sb->ptr = base + offset;
return JS_TRUE;
}
JSBool
js_InitTokenStream(JSContext *cx, JSTokenStream *ts,
const jschar *base, size_t length,
FILE *fp, const char *filename, uintN lineno)
bool
JSTokenStream::init(JSContext *cx, const jschar *base, size_t length,
FILE *fp, const char *fn, uintN ln)
{
jschar *buf;
size_t nb;
@ -231,34 +197,33 @@ js_InitTokenStream(JSContext *cx, JSTokenStream *ts,
JS_ARENA_ALLOCATE_CAST(buf, jschar *, &cx->tempPool, nb);
if (!buf) {
js_ReportOutOfScriptQuota(cx);
return JS_FALSE;
return false;
}
memset(buf, 0, nb);
memset(ts, 0, sizeof(*ts));
ts->filename = filename;
ts->lineno = lineno;
ts->linebuf.base = ts->linebuf.limit = ts->linebuf.ptr = buf;
/* Initialize members. */
filename = fn;
lineno = ln;
linebuf.base = linebuf.limit = linebuf.ptr = buf;
if (fp) {
ts->file = fp;
ts->userbuf.base = buf + JS_LINE_LIMIT;
ts->userbuf.ptr = ts->userbuf.limit = ts->userbuf.base + JS_LINE_LIMIT;
file = fp;
userbuf.base = buf + JS_LINE_LIMIT;
userbuf.ptr = userbuf.limit = userbuf.base + JS_LINE_LIMIT;
} else {
ts->userbuf.base = (jschar *)base;
ts->userbuf.limit = (jschar *)base + length;
ts->userbuf.ptr = (jschar *)base;
userbuf.base = (jschar *)base;
userbuf.limit = (jschar *)base + length;
userbuf.ptr = (jschar *)base;
}
ts->tokenbuf.grow = GrowTokenBuf;
ts->tokenbuf.data = cx;
ts->listener = cx->debugHooks->sourceHandler;
ts->listenerData = cx->debugHooks->sourceHandlerData;
return JS_TRUE;
listener = cx->debugHooks->sourceHandler;
listenerData = cx->debugHooks->sourceHandlerData;
return true;
}
void
js_CloseTokenStream(JSContext *cx, JSTokenStream *ts)
JSTokenStream::close(JSContext *cx)
{
if (ts->flags & TSF_OWNFILENAME)
cx->free((void *) ts->filename);
if (flags & TSF_OWNFILENAME)
cx->free((void *) filename);
}
#ifdef XP_WIN
@ -684,138 +649,8 @@ js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
return warning;
}
static JSBool
GrowStringBuffer(JSStringBuffer *sb, size_t amount)
{
ptrdiff_t offset = sb->ptr - sb->base;
JS_ASSERT(offset >= 0);
/*
* This addition needs an overflow check, but we can defer bounding against
* ~size_t(0) / sizeof(jschar) till later to consolidate that test.
*/
size_t newlength = offset + amount + 1;
if (size_t(offset) < newlength) {
/* Grow by powers of two until 16MB, then grow by that chunk size. */
const size_t CHUNK_SIZE_MASK = JS_BITMASK(24);
if (newlength <= CHUNK_SIZE_MASK)
newlength = JS_BIT(JS_CeilingLog2(newlength));
else if (newlength & CHUNK_SIZE_MASK)
newlength = (newlength | CHUNK_SIZE_MASK) + 1;
/* Now do the full overflow check. */
if (size_t(offset) < newlength && newlength < ~size_t(0) / sizeof(jschar)) {
jschar *bp = (jschar *) js_realloc(sb->base, newlength * sizeof(jschar));
if (bp) {
sb->base = bp;
sb->ptr = bp + offset;
sb->limit = bp + newlength - 1;
return true;
}
}
}
/* Either newlength overflow or realloc failure: poison the well. */
js_free(sb->base);
sb->base = STRING_BUFFER_ERROR_BASE;
return false;
}
static void
FreeStringBuffer(JSStringBuffer *sb)
{
JS_ASSERT(STRING_BUFFER_OK(sb));
if (sb->base)
js_free(sb->base);
}
void
js_InitStringBuffer(JSStringBuffer *sb)
{
sb->base = sb->limit = sb->ptr = NULL;
sb->data = NULL;
sb->grow = GrowStringBuffer;
sb->free = FreeStringBuffer;
}
void
js_FinishStringBuffer(JSStringBuffer *sb)
{
sb->free(sb);
}
void
js_AppendChar(JSStringBuffer *sb, jschar c)
{
jschar *bp;
if (!STRING_BUFFER_OK(sb))
return;
if (!ENSURE_STRING_BUFFER(sb, 1))
return;
bp = sb->ptr;
*bp++ = c;
*bp = 0;
sb->ptr = bp;
}
void
js_AppendUCString(JSStringBuffer *sb, const jschar *buf, uintN len)
{
jschar *bp;
if (!STRING_BUFFER_OK(sb))
return;
if (len == 0 || !ENSURE_STRING_BUFFER(sb, len))
return;
bp = sb->ptr;
js_strncpy(bp, buf, len);
bp += len;
*bp = 0;
sb->ptr = bp;
}
#if JS_HAS_XML_SUPPORT
void
js_RepeatChar(JSStringBuffer *sb, jschar c, uintN count)
{
jschar *bp;
if (!STRING_BUFFER_OK(sb) || count == 0)
return;
if (!ENSURE_STRING_BUFFER(sb, count))
return;
for (bp = sb->ptr; count; --count)
*bp++ = c;
*bp = 0;
sb->ptr = bp;
}
void
js_AppendCString(JSStringBuffer *sb, const char *asciiz)
{
size_t length;
jschar *bp;
if (!STRING_BUFFER_OK(sb) || *asciiz == '\0')
return;
length = strlen(asciiz);
if (!ENSURE_STRING_BUFFER(sb, length))
return;
for (bp = sb->ptr; length; --length)
*bp++ = (jschar) *asciiz++;
*bp = 0;
sb->ptr = bp;
}
void
js_AppendJSString(JSStringBuffer *sb, JSString *str)
{
js_AppendUCString(sb, str->chars(), str->length());
}
static JSBool
GetXMLEntity(JSContext *cx, JSTokenStream *ts)
{
@ -826,10 +661,11 @@ GetXMLEntity(JSContext *cx, JSTokenStream *ts)
char *bytes;
JSErrNum msg;
JSCharBuffer &tb = ts->tokenbuf;
/* Put the entity, including the '&' already scanned, in ts->tokenbuf. */
offset = ts->tokenbuf.ptr - ts->tokenbuf.base;
js_FastAppendChar(&ts->tokenbuf, '&');
if (!STRING_BUFFER_OK(&ts->tokenbuf))
offset = tb.length();
if (!tb.append('&'))
return JS_FALSE;
while ((c = GetChar(ts)) != ';') {
if (c == EOF || c == '\n') {
@ -837,14 +673,13 @@ GetXMLEntity(JSContext *cx, JSTokenStream *ts)
JSMSG_END_OF_XML_ENTITY);
return JS_FALSE;
}
js_FastAppendChar(&ts->tokenbuf, (jschar) c);
if (!STRING_BUFFER_OK(&ts->tokenbuf))
if (!tb.append(c))
return JS_FALSE;
}
/* Let length be the number of jschars after the '&', including the ';'. */
length = (ts->tokenbuf.ptr - ts->tokenbuf.base) - offset;
bp = ts->tokenbuf.base + offset;
length = tb.length() - offset;
bp = tb.begin() + offset;
c = d = 0;
ispair = JS_FALSE;
if (length > 2 && bp[1] == '#') {
@ -917,18 +752,15 @@ GetXMLEntity(JSContext *cx, JSTokenStream *ts)
*bp++ = (jschar) c;
if (ispair)
*bp++ = (jschar) d;
*bp = 0;
ts->tokenbuf.ptr = bp;
tb.shrinkBy(tb.end() - bp);
return JS_TRUE;
badncr:
msg = JSMSG_BAD_XML_NCR;
bad:
/* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */
JS_ASSERT(STRING_BUFFER_OK(&ts->tokenbuf));
JS_ASSERT((ts->tokenbuf.ptr - bp) >= 1);
bytes = js_DeflateString(cx, bp + 1,
(ts->tokenbuf.ptr - bp) - 1);
JS_ASSERT((tb.end() - bp) >= 1);
bytes = js_DeflateString(cx, bp + 1, (tb.end() - bp) - 1);
if (bytes) {
js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
msg, bytes);
@ -1015,6 +847,12 @@ ScanAsSpace(jschar c)
return JS_FALSE;
}
static JS_ALWAYS_INLINE JSAtom *
atomize(JSContext *cx, JSCharBuffer &cb)
{
return js_AtomizeChars(cx, cb.begin(), cb.length(), 0);
}
JSTokenType
js_GetToken(JSContext *cx, JSTokenStream *ts)
{
@ -1030,27 +868,7 @@ js_GetToken(JSContext *cx, JSTokenStream *ts)
ptrdiff_t contentIndex;
#endif
#define INIT_TOKENBUF() (ts->tokenbuf.ptr = ts->tokenbuf.base)
#define TOKENBUF_LENGTH() (ts->tokenbuf.ptr - ts->tokenbuf.base)
#define TOKENBUF_OK() STRING_BUFFER_OK(&ts->tokenbuf)
#define TOKENBUF_TO_ATOM() (TOKENBUF_OK() \
? js_AtomizeChars(cx, \
TOKENBUF_BASE(), \
TOKENBUF_LENGTH(), \
0) \
: NULL)
#define ADD_TO_TOKENBUF(c) JS_BEGIN_MACRO \
js_FastAppendChar(&ts->tokenbuf, jschar(c)); \
if (!TOKENBUF_OK()) \
goto error; \
JS_END_MACRO
/* The following 4 macros should only be used when TOKENBUF_OK() is true. */
#define TOKENBUF_BASE() (ts->tokenbuf.base)
#define TOKENBUF_END() (ts->tokenbuf.ptr)
#define TOKENBUF_CHAR(i) (ts->tokenbuf.base[i])
#define TRIM_TOKENBUF(i) (ts->tokenbuf.ptr = ts->tokenbuf.base + i)
#define NUL_TERM_TOKENBUF() (*ts->tokenbuf.ptr = 0)
JSCharBuffer &tb = ts->tokenbuf;
/* Check for a pushed-back token resulting from mismatching lookahead. */
while (ts->lookahead != 0) {
@ -1070,7 +888,7 @@ js_GetToken(JSContext *cx, JSTokenStream *ts)
if (ts->flags & TSF_XMLTEXTMODE) {
tt = TOK_XMLSPACE; /* veto if non-space, return TOK_XMLTEXT */
tp = NewToken(ts, 0);
INIT_TOKENBUF();
tb.clear();
qc = (ts->flags & TSF_XMLONLYMODE) ? '<' : '{';
while ((c = GetChar(ts)) != qc && c != '<' && c != EOF) {
@ -1083,14 +901,15 @@ js_GetToken(JSContext *cx, JSTokenStream *ts)
if (!JS_ISXMLSPACE(c))
tt = TOK_XMLTEXT;
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
}
UngetChar(ts, c);
if (TOKENBUF_LENGTH() == 0) {
if (tb.empty()) {
atom = NULL;
} else {
atom = TOKENBUF_TO_ATOM();
atom = atomize(cx, tb);
if (!atom)
goto error;
}
@ -1117,11 +936,12 @@ js_GetToken(JSContext *cx, JSTokenStream *ts)
goto out;
}
INIT_TOKENBUF();
tb.clear();
if (JS_ISXMLNSSTART(c)) {
JSBool sawColon = JS_FALSE;
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
while ((c = GetChar(ts)) != EOF && JS_ISXMLNAME(c)) {
if (c == ':') {
int nextc;
@ -1138,11 +958,12 @@ js_GetToken(JSContext *cx, JSTokenStream *ts)
sawColon = JS_TRUE;
}
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
}
UngetChar(ts, c);
atom = TOKENBUF_TO_ATOM();
atom = atomize(cx, tb);
if (!atom)
goto error;
tp->t_op = JSOP_STRING;
@ -1179,7 +1000,9 @@ js_GetToken(JSContext *cx, JSTokenStream *ts)
*/
if (c == '"' && !(ts->flags & TSF_XMLONLYMODE)) {
JS_ASSERT(qc == '\'');
js_AppendCString(&ts->tokenbuf, js_quot_entity_str);
if (!tb.append(js_quot_entity_str,
strlen(js_quot_entity_str)))
goto error;
continue;
}
@ -1189,9 +1012,10 @@ js_GetToken(JSContext *cx, JSTokenStream *ts)
continue;
}
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
}
atom = TOKENBUF_TO_ATOM();
atom = atomize(cx, tb);
if (!atom)
goto error;
tp->pos.end.lineno = (uint16)ts->lineno;
@ -1244,9 +1068,10 @@ retry:
hadUnicodeEscape = JS_ISIDSTART(qc)))) {
if (hadUnicodeEscape)
c = qc;
INIT_TOKENBUF();
tb.clear();
for (;;) {
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
c = GetChar(ts);
if (c == '\\') {
qc = GetUnicodeEscape(ts);
@ -1267,8 +1092,7 @@ retry:
*/
if (!hadUnicodeEscape &&
!(ts->flags & TSF_KEYWORD_IS_NAME) &&
TOKENBUF_OK() &&
(kw = FindKeyword(TOKENBUF_BASE(), TOKENBUF_LENGTH()))) {
(kw = FindKeyword(tb.begin(), tb.length()))) {
if (kw->tokentype == TOK_RESERVED) {
if (!js_ReportCompileErrorNumber(cx, ts, NULL,
JSREPORT_WARNING |
@ -1284,7 +1108,7 @@ retry:
}
}
atom = TOKENBUF_TO_ATOM();
atom = atomize(cx, tb);
if (!atom)
goto error;
tp->t_op = JSOP_NAME;
@ -1299,13 +1123,15 @@ retry:
jsdouble dval;
radix = 10;
INIT_TOKENBUF();
tb.clear();
if (c == '0') {
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
c = GetChar(ts);
if (JS_TOLOWER(c) == 'x') {
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
c = GetChar(ts);
radix = 16;
} else if (JS7_ISDEC(c)) {
@ -1333,22 +1159,26 @@ retry:
radix = 10;
}
}
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
c = GetChar(ts);
}
if (radix == 10 && (c == '.' || JS_TOLOWER(c) == 'e')) {
if (c == '.') {
do {
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
c = GetChar(ts);
} while (JS7_ISDEC(c));
}
if (JS_TOLOWER(c) == 'e') {
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
c = GetChar(ts);
if (c == '+' || c == '-') {
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
c = GetChar(ts);
}
if (!JS7_ISDEC(c)) {
@ -1357,7 +1187,8 @@ retry:
goto error;
}
do {
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
c = GetChar(ts);
} while (JS7_ISDEC(c));
}
@ -1365,19 +1196,17 @@ retry:
/* Put back the next char and NUL-terminate tokenbuf for js_strto*. */
UngetChar(ts, c);
ADD_TO_TOKENBUF(0);
if (!TOKENBUF_OK())
if (!tb.append(0))
goto error;
if (radix == 10) {
if (!js_strtod(cx, TOKENBUF_BASE(), TOKENBUF_END(),
&endptr, &dval)) {
if (!js_strtod(cx, tb.begin(), tb.end(), &endptr, &dval)) {
js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
JSMSG_OUT_OF_MEMORY);
goto error;
}
} else {
if (!js_strtointeger(cx, TOKENBUF_BASE(), TOKENBUF_END(),
if (!js_strtointeger(cx, tb.begin(), tb.end(),
&endptr, radix, &dval)) {
js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
JSMSG_OUT_OF_MEMORY);
@ -1391,7 +1220,7 @@ retry:
if (c == '"' || c == '\'') {
qc = c;
INIT_TOKENBUF();
tb.clear();
while ((c = GetChar(ts)) != qc) {
if (c == '\n' || c == EOF) {
UngetChar(ts, c);
@ -1453,9 +1282,10 @@ retry:
break;
}
}
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
}
atom = TOKENBUF_TO_ATOM();
atom = atomize(cx, tb);
if (!atom)
goto error;
tp->pos.end.lineno = (uint16)ts->lineno;
@ -1593,7 +1423,7 @@ retry:
(JS_HAS_XML_OPTION(cx) || PeekChar(ts) != '!')) {
/* Check for XML comment or CDATA section. */
if (MatchChar(ts, '!')) {
INIT_TOKENBUF();
tb.clear();
/* Scan XML comment. */
if (MatchChar(ts, '-')) {
@ -1602,7 +1432,8 @@ retry:
while ((c = GetChar(ts)) != '-' || !MatchChar(ts, '-')) {
if (c == EOF)
goto bad_xml_markup;
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
}
tt = TOK_XMLCOMMENT;
tp->t_op = JSOP_XMLCOMMENT;
@ -1626,7 +1457,8 @@ retry:
cp[1] != '>') {
if (c == EOF)
goto bad_xml_markup;
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
}
GetChar(ts); /* discard ] but not > */
tt = TOK_XMLCDATA;
@ -1643,17 +1475,17 @@ retry:
targetLength = 0;
contentIndex = -1;
INIT_TOKENBUF();
tb.clear();
while ((c = GetChar(ts)) != '?' || PeekChar(ts) != '>') {
if (c == EOF)
goto bad_xml_markup;
if (inTarget) {
if (JS_ISXMLSPACE(c)) {
if (TOKENBUF_LENGTH() == 0)
if (tb.empty())
goto bad_xml_markup;
inTarget = JS_FALSE;
} else {
if (!((TOKENBUF_LENGTH() == 0)
if (!(tb.empty()
? JS_ISXMLNSSTART(c)
: JS_ISXMLNS(c))) {
goto bad_xml_markup;
@ -1662,32 +1494,31 @@ retry:
}
} else {
if (contentIndex < 0 && !JS_ISXMLSPACE(c))
contentIndex = TOKENBUF_LENGTH();
contentIndex = tb.length();
}
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
}
if (targetLength == 0)
goto bad_xml_markup;
if (!TOKENBUF_OK())
goto error;
if (contentIndex < 0) {
atom = cx->runtime->atomState.emptyAtom;
} else {
atom = js_AtomizeChars(cx,
&TOKENBUF_CHAR(contentIndex),
TOKENBUF_LENGTH() - contentIndex,
tb.begin() + contentIndex,
tb.length() - contentIndex,
0);
if (!atom)
goto error;
}
TRIM_TOKENBUF(targetLength);
tb.shrinkBy(tb.length() - targetLength);
tp->t_atom2 = atom;
tt = TOK_XMLPI;
finish_xml_markup:
if (!MatchChar(ts, '>'))
goto bad_xml_markup;
atom = TOKENBUF_TO_ATOM();
atom = atomize(cx, tb);
if (!atom)
goto error;
tp->t_atom = atom;
@ -1849,7 +1680,7 @@ skipline:
uintN flags, length;
JSBool inCharClass = JS_FALSE;
INIT_TOKENBUF();
tb.clear();
for (;;) {
c = GetChar(ts);
if (c == '\n' || c == EOF) {
@ -1859,7 +1690,8 @@ skipline:
goto error;
}
if (c == '\\') {
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
c = GetChar(ts);
} else if (c == '[') {
inCharClass = JS_TRUE;
@ -1869,9 +1701,10 @@ skipline:
/* For compat with IE, allow unescaped / in char classes. */
break;
}
ADD_TO_TOKENBUF(c);
if (!tb.append(c))
goto error;
}
for (flags = 0, length = TOKENBUF_LENGTH() + 1; ; length++) {
for (flags = 0, length = tb.length() + 1; ; length++) {
c = PeekChar(ts);
if (c == 'g' && !(flags & JSREG_GLOB))
flags |= JSREG_GLOB;
@ -1895,10 +1728,6 @@ skipline:
(void) GetChar(ts);
goto error;
}
/* XXXbe fix jsregexp.c so it doesn't depend on NUL termination */
if (!TOKENBUF_OK())
goto error;
NUL_TERM_TOKENBUF();
tp->t_reflags = flags;
tt = TOK_REGEXP;
break;
@ -2006,8 +1835,6 @@ out:
ts->flags |= TSF_DIRTYLINE;
eol_out:
if (!STRING_BUFFER_OK(&ts->tokenbuf))
tt = TOK_ERROR;
JS_ASSERT(tt < TOK_LIMIT);
tp->pos.end.index = ts->linepos +
(ts->linebuf.ptr - ts->linebuf.base) -
@ -2019,16 +1846,6 @@ error:
tt = TOK_ERROR;
ts->flags |= TSF_ERROR;
goto out;
#undef INIT_TOKENBUF
#undef TOKENBUF_LENGTH
#undef TOKENBUF_OK
#undef TOKENBUF_TO_ATOM
#undef ADD_TO_TOKENBUF
#undef TOKENBUF_BASE
#undef TOKENBUF_CHAR
#undef TRIM_TOKENBUF
#undef NUL_TERM_TOKENBUF
}
void

Просмотреть файл

@ -48,6 +48,7 @@
#include "jsopcode.h"
#include "jsprvtd.h"
#include "jspubtd.h"
#include "jsvector.h"
JS_BEGIN_EXTERN_C
@ -161,73 +162,6 @@ typedef enum JSTokenType {
# define TOKEN_TYPE_IS_DECL(tt) ((tt) == TOK_VAR)
#endif
struct JSStringBuffer {
jschar *base;
jschar *limit; /* length limit for quick bounds check */
jschar *ptr; /* slot for next non-NUL char to store */
void *data;
JSBool (*grow)(JSStringBuffer *sb, size_t newlength);
void (*free)(JSStringBuffer *sb);
};
#define STRING_BUFFER_ERROR_BASE ((jschar *) 1)
#define STRING_BUFFER_OK(sb) ((sb)->base != STRING_BUFFER_ERROR_BASE)
#define STRING_BUFFER_OFFSET(sb) ((sb)->ptr -(sb)->base)
extern void
js_InitStringBuffer(JSStringBuffer *sb);
extern void
js_FinishStringBuffer(JSStringBuffer *sb);
static inline void
js_RewindStringBuffer(JSStringBuffer *sb)
{
JS_ASSERT(STRING_BUFFER_OK(sb));
sb->ptr = sb->base;
}
#define ENSURE_STRING_BUFFER(sb,n) \
((sb)->ptr + (n) <= (sb)->limit || sb->grow(sb, n))
/*
* NB: callers are obligated to test STRING_BUFFER_OK(sb) after this returns,
* before calling it again -- but not necessarily before calling other sb ops
* declared in this header file.
*
* Thus multiple calls, to ops other than this one that check STRING_BUFFER_OK
* and suppress updating sb if true, can consolidate the final STRING_BUFFER_OK
* test that conditions a JS_ReportOutOfMemory (if necessary -- the grow hook
* can report OOM early, obviating the need for the callers to report).
*
* This style of error checking is not obviously better, and it could be worse
* in efficiency, than the propagated failure return code style used elsewhere
* in the engine. I view it as a failed experiment. /be
*/
static inline void
js_FastAppendChar(JSStringBuffer *sb, jschar c)
{
JS_ASSERT(STRING_BUFFER_OK(sb));
if (!ENSURE_STRING_BUFFER(sb, 1))
return;
*sb->ptr++ = c;
}
extern void
js_AppendChar(JSStringBuffer *sb, jschar c);
extern void
js_RepeatChar(JSStringBuffer *sb, jschar c, uintN count);
extern void
js_AppendCString(JSStringBuffer *sb, const char *asciiz);
extern void
js_AppendUCString(JSStringBuffer *sb, const jschar *buf, uintN len);
extern void
js_AppendJSString(JSStringBuffer *sb, JSString *str);
struct JSTokenPtr {
uint32 index; /* index of char in physical line */
uint32 lineno; /* physical line number */
@ -320,7 +254,6 @@ struct JSTokenStream {
uint32 linepos; /* linebuf offset in physical line */
JSTokenBuf linebuf; /* line buffer for diagnostics */
JSTokenBuf userbuf; /* user input buffer if !file */
JSStringBuffer tokenbuf; /* current token string buffer */
const char *filename; /* input filename or null */
FILE *file; /* stdio stream if reading from file */
JSSourceHandler listener; /* callback for source; eg debugger */
@ -328,6 +261,29 @@ struct JSTokenStream {
void *listenerTSData;/* listener data for this TokenStream */
jschar *saveEOL; /* save next end of line in userbuf, to
optimize for very long lines */
JSCharBuffer tokenbuf; /* current token string buffer */
/*
* To construct a JSTokenStream, first call the constructor, which is
* infallible, then call |init|, which can fail. To destroy a JSTokenStream,
* first call |close| then call the destructor. If |init| fails, do not call
* |close|.
*
* This class uses JSContext.tempPool to allocate internal buffers. The
* caller should JS_ARENA_MARK before calling |init| and JS_ARENA_RELEASE
* after calling |close|.
*/
JSTokenStream(JSContext *);
/*
* Create a new token stream, either from an input buffer or from a file.
* Return false on file-open or memory-allocation failure.
*/
bool init(JSContext *, const jschar *base, size_t length,
FILE *fp, const char *filename, uintN lineno);
void close(JSContext *);
~JSTokenStream() {}
};
#define CURRENT_TOKEN(ts) ((ts)->tokens[(ts)->cursor])
@ -380,19 +336,6 @@ struct JSTokenStream {
#define LINE_SEPARATOR 0x2028
#define PARA_SEPARATOR 0x2029
/*
* Create a new token stream, either from an input buffer or from a file.
* Return null on file-open or memory-allocation failure.
*
* The function uses JSContext.tempPool to allocate internal buffers. The
* caller should release them using JS_ARENA_RELEASE after it has finished
* with the token stream and has called js_CloseTokenStream.
*/
extern JSBool
js_InitTokenStream(JSContext *cx, JSTokenStream *ts,
const jschar *base, size_t length,
FILE *fp, const char *filename, uintN lineno);
extern void
js_CloseTokenStream(JSContext *cx, JSTokenStream *ts);

Просмотреть файл

@ -2737,7 +2737,7 @@ js_NewStringFromCharBuffer(JSContext *cx, JSCharBuffer &cb)
if (cb.empty())
return ATOM_TO_STRING(cx->runtime->atomState.emptyAtom);
size_t length = cb.size();
size_t length = cb.length();
if (!cb.append('\0'))
return NULL;

Просмотреть файл

@ -198,7 +198,7 @@ struct JSTempVectorImpl
new(dst) T(*src);
JSTempVectorImpl::destroy(v.heapBegin(), v.heapEnd());
v.mCx->free(v.heapBegin());
v.heapEnd() = newbuf + v.heapSize();
v.heapEnd() = newbuf + v.heapLength();
v.heapBegin() = newbuf;
v.heapCapacity() = newcap;
return true;
@ -252,7 +252,7 @@ struct JSTempVectorImpl<T, N, true>
T *newbuf = reinterpret_cast<T *>(v.mCx->realloc(v.heapBegin(), bytes));
if (!newbuf)
return false;
v.heapEnd() = newbuf + v.heapSize();
v.heapEnd() = newbuf + v.heapLength();
v.heapBegin() = newbuf;
v.heapCapacity() = newcap;
return true;
@ -282,9 +282,9 @@ class JSTempVector
typedef JSTempVectorImpl<T, N, JSUtils::IsPodType<T>::result> Impl;
friend struct JSTempVectorImpl<T, N, JSUtils::IsPodType<T>::result>;
bool calculateNewCapacity(size_t curSize, size_t sizeInc, size_t &newCap);
bool growHeapStorageBy(size_t sizeInc);
bool convertToHeapStorage(size_t sizeInc);
bool calculateNewCapacity(size_t curLength, size_t lengthInc, size_t &newCap);
bool growHeapStorageBy(size_t lengthInc);
bool convertToHeapStorage(size_t lengthInc);
/* magic constants */
@ -303,10 +303,10 @@ class JSTempVector
/*
* Since a vector either stores elements inline or in a heap-allocated
* buffer, reuse the storage. mSizeOrCapacity serves as the union
* buffer, reuse the storage. mLengthOrCapacity serves as the union
* discriminator. In inline mode (when elements are stored in u.mBuf),
* mSizeOrCapacity holds the vector's size. In heap mode (when elements
* are stored in [u.ptrs.mBegin, u.ptrs.mEnd)), mSizeOrCapacity holds the
* mLengthOrCapacity holds the vector's length. In heap mode (when elements
* are stored in [u.ptrs.mBegin, u.ptrs.mEnd)), mLengthOrCapacity holds the
* vector's capacity.
*/
static const size_t sInlineCapacity =
@ -317,8 +317,8 @@ class JSTempVector
JSContext *mCx;
size_t mSizeOrCapacity;
bool usingInlineStorage() const { return mSizeOrCapacity <= sInlineCapacity; }
size_t mLengthOrCapacity;
bool usingInlineStorage() const { return mLengthOrCapacity <= sInlineCapacity; }
union {
BufferPtrs ptrs;
@ -326,14 +326,14 @@ class JSTempVector
} u;
/* Only valid when usingInlineStorage() */
size_t &inlineSize() {
size_t &inlineLength() {
JS_ASSERT(usingInlineStorage());
return mSizeOrCapacity;
return mLengthOrCapacity;
}
size_t inlineSize() const {
size_t inlineLength() const {
JS_ASSERT(usingInlineStorage());
return mSizeOrCapacity;
return mLengthOrCapacity;
}
T *inlineBegin() const {
@ -343,11 +343,11 @@ class JSTempVector
T *inlineEnd() const {
JS_ASSERT(usingInlineStorage());
return ((T *)u.mBuf) + mSizeOrCapacity;
return ((T *)u.mBuf) + mLengthOrCapacity;
}
/* Only valid when !usingInlineStorage() */
size_t heapSize() const {
size_t heapLength() const {
JS_ASSERT(!usingInlineStorage());
/* Guaranteed by calculateNewCapacity. */
JS_ASSERT(size_t(u.ptrs.mEnd - u.ptrs.mBegin) ==
@ -357,7 +357,7 @@ class JSTempVector
size_t &heapCapacity() {
JS_ASSERT(!usingInlineStorage());
return mSizeOrCapacity;
return mLengthOrCapacity;
}
T *&heapBegin() {
@ -372,7 +372,7 @@ class JSTempVector
size_t heapCapacity() const {
JS_ASSERT(!usingInlineStorage());
return mSizeOrCapacity;
return mLengthOrCapacity;
}
T *heapBegin() const {
@ -413,7 +413,7 @@ class JSTempVector
public:
JSTempVector(JSContext *cx)
: mCx(cx), mSizeOrCapacity(0)
: mCx(cx), mLengthOrCapacity(0)
#ifdef DEBUG
, mInProgress(false)
#endif
@ -422,12 +422,12 @@ class JSTempVector
/* accessors */
size_t size() const {
return usingInlineStorage() ? inlineSize() : heapSize();
size_t length() const {
return usingInlineStorage() ? inlineLength() : heapLength();
}
bool empty() const {
return usingInlineStorage() ? inlineSize() == 0 : heapBegin() == heapEnd();
return usingInlineStorage() ? inlineLength() == 0 : heapBegin() == heapEnd();
}
size_t capacity() const {
@ -455,12 +455,12 @@ class JSTempVector
}
T &operator[](size_t i) {
JS_ASSERT(!mInProgress && i < size());
JS_ASSERT(!mInProgress && i < length());
return begin()[i];
}
const T &operator[](size_t i) const {
JS_ASSERT(!mInProgress && i < size());
JS_ASSERT(!mInProgress && i < length());
return begin()[i];
}
@ -489,8 +489,8 @@ class JSTempVector
*/
bool growBy(size_t incr);
/* Call shrinkBy or growBy based on whether newSize > size(). */
bool resize(size_t newSize);
/* Call shrinkBy or growBy based on whether newSize > length(). */
bool resize(size_t newLength);
void clear();
@ -507,7 +507,7 @@ class JSTempVector
* buffer may need to be allocated (if the elements are currently
* stored in-place), the call can fail, returning NULL.
*
* N.B. Although a T*, only the range [0, size()) is constructed.
* N.B. Although a T*, only the range [0, length()) is constructed.
*/
T *extractRawBuffer();
@ -526,11 +526,11 @@ class JSTempVector
* literal to a vector. This could not be done generically since one must take
* care not to append the terminating '\0'.
*/
template <class T, size_t N, size_t ArraySize>
template <class T, size_t N, size_t ArrayLength>
bool
js_AppendLiteral(JSTempVector<T,N> &v, const char (&array)[ArraySize])
js_AppendLiteral(JSTempVector<T,N> &v, const char (&array)[ArrayLength])
{
return v.append(array, array + ArraySize - 1);
return v.append(array, array + ArrayLength - 1);
}
@ -550,21 +550,21 @@ JSTempVector<T,N>::~JSTempVector()
}
/*
* Calculate a new capacity size that is at least sizeInc greater than
* curSize and check for overflow.
* Calculate a new capacity that is at least lengthInc greater than
* curLength and check for overflow.
*/
template <class T, size_t N>
inline bool
JSTempVector<T,N>::calculateNewCapacity(size_t curSize, size_t sizeInc,
JSTempVector<T,N>::calculateNewCapacity(size_t curLength, size_t lengthInc,
size_t &newCap)
{
size_t newMinCap = curSize + sizeInc;
size_t newMinCap = curLength + lengthInc;
/*
* Check for overflow in the above addition, below CEILING_LOG2, and later
* multiplication by sizeof(T).
*/
if (newMinCap < curSize ||
if (newMinCap < curLength ||
newMinCap & JSUtils::MulOverflowMask<2 * sizeof(T)>::result) {
js_ReportAllocationOverflow(mCx);
return false;
@ -589,28 +589,28 @@ JSTempVector<T,N>::calculateNewCapacity(size_t curSize, size_t sizeInc,
/*
* This function will grow the current heap capacity to have capacity
* (heapSize() + sizeInc) and fail on OOM or integer overflow.
* (heapLength() + lengthInc) and fail on OOM or integer overflow.
*/
template <class T, size_t N>
inline bool
JSTempVector<T,N>::growHeapStorageBy(size_t sizeInc)
JSTempVector<T,N>::growHeapStorageBy(size_t lengthInc)
{
size_t newCap;
return calculateNewCapacity(heapSize(), sizeInc, newCap) &&
return calculateNewCapacity(heapLength(), lengthInc, newCap) &&
Impl::growTo(*this, newCap);
}
/*
* This function will create a new heap buffer with capacity (inlineSize() +
* sizeInc()), move all elements in the inline buffer to this new buffer,
* This function will create a new heap buffer with capacity (inlineLength() +
* lengthInc()), move all elements in the inline buffer to this new buffer,
* and fail on OOM or integer overflow.
*/
template <class T, size_t N>
inline bool
JSTempVector<T,N>::convertToHeapStorage(size_t sizeInc)
JSTempVector<T,N>::convertToHeapStorage(size_t lengthInc)
{
size_t newCap;
if (!calculateNewCapacity(inlineSize(), sizeInc, newCap))
if (!calculateNewCapacity(inlineLength(), lengthInc, newCap))
return false;
/* Allocate buffer. */
@ -619,14 +619,14 @@ JSTempVector<T,N>::convertToHeapStorage(size_t sizeInc)
return false;
/* Copy inline elements into heap buffer. */
size_t size = inlineSize();
size_t length = inlineLength();
Impl::copyConstruct(newBuf, inlineBegin(), inlineEnd());
Impl::destroy(inlineBegin(), inlineEnd());
/* Switch in heap buffer. */
mSizeOrCapacity = newCap; /* marks us as !usingInlineStorage() */
mLengthOrCapacity = newCap; /* marks us as !usingInlineStorage() */
heapBegin() = newBuf;
heapEnd() = newBuf + size;
heapEnd() = newBuf + length;
return true;
}
@ -637,10 +637,10 @@ JSTempVector<T,N>::reserve(size_t request)
ReentrancyGuard g(*this);
if (usingInlineStorage()) {
if (request > sInlineCapacity)
return convertToHeapStorage(request - inlineSize());
return convertToHeapStorage(request - inlineLength());
} else {
if (request > heapCapacity())
return growHeapStorageBy(request - heapSize());
return growHeapStorageBy(request - heapLength());
}
return true;
}
@ -650,10 +650,10 @@ inline void
JSTempVector<T,N>::shrinkBy(size_t incr)
{
ReentrancyGuard g(*this);
JS_ASSERT(incr <= size());
JS_ASSERT(incr <= length());
if (usingInlineStorage()) {
Impl::destroy(inlineEnd() - incr, inlineEnd());
inlineSize() -= incr;
inlineLength() -= incr;
} else {
Impl::destroy(heapEnd() - incr, heapEnd());
heapEnd() -= incr;
@ -666,12 +666,12 @@ JSTempVector<T,N>::growBy(size_t incr)
{
ReentrancyGuard g(*this);
if (usingInlineStorage()) {
size_t freespace = sInlineCapacity - inlineSize();
size_t freespace = sInlineCapacity - inlineLength();
if (incr <= freespace) {
T *newend = inlineEnd() + incr;
if (!JSUtils::IsPodType<T>::result)
Impl::initialize(inlineEnd(), newend);
inlineSize() += incr;
inlineLength() += incr;
JS_ASSERT(usingInlineStorage());
return true;
}
@ -680,7 +680,7 @@ JSTempVector<T,N>::growBy(size_t incr)
}
else {
/* grow if needed */
size_t freespace = heapCapacity() - heapSize();
size_t freespace = heapCapacity() - heapLength();
if (incr > freespace) {
if (!growHeapStorageBy(incr))
return false;
@ -688,7 +688,7 @@ JSTempVector<T,N>::growBy(size_t incr)
}
/* We are !usingInlineStorage(). Initialize new elements. */
JS_ASSERT(heapCapacity() - heapSize() >= incr);
JS_ASSERT(heapCapacity() - heapLength() >= incr);
T *newend = heapEnd() + incr;
if (!JSUtils::IsPodType<T>::result)
Impl::initialize(heapEnd(), newend);
@ -698,12 +698,12 @@ JSTempVector<T,N>::growBy(size_t incr)
template <class T, size_t N>
inline bool
JSTempVector<T,N>::resize(size_t newsize)
JSTempVector<T,N>::resize(size_t newLength)
{
size_t cursize = size();
if (newsize > cursize)
return growBy(newsize - cursize);
shrinkBy(cursize - newsize);
size_t curLength = length();
if (newLength > curLength)
return growBy(newLength - curLength);
shrinkBy(curLength - newLength);
return true;
}
@ -714,7 +714,7 @@ JSTempVector<T,N>::clear()
ReentrancyGuard g(*this);
if (usingInlineStorage()) {
Impl::destroy(inlineBegin(), inlineEnd());
inlineSize() = 0;
inlineLength() = 0;
}
else {
Impl::destroy(heapBegin(), heapEnd());
@ -728,21 +728,21 @@ JSTempVector<T,N>::append(const T &t)
{
ReentrancyGuard g(*this);
if (usingInlineStorage()) {
if (inlineSize() < sInlineCapacity) {
if (inlineLength() < sInlineCapacity) {
new(inlineEnd()) T(t);
++inlineSize();
++inlineLength();
JS_ASSERT(usingInlineStorage());
return true;
}
if (!convertToHeapStorage(1))
return false;
} else {
if (heapSize() == heapCapacity() && !growHeapStorageBy(1))
if (heapLength() == heapCapacity() && !growHeapStorageBy(1))
return false;
}
/* We are !usingInlineStorage(). Initialize new elements. */
JS_ASSERT(heapSize() <= heapCapacity() && heapCapacity() - heapSize() >= 1);
JS_ASSERT(heapLength() <= heapCapacity() && heapCapacity() - heapLength() >= 1);
new(heapEnd()++) T(t);
return true;
}
@ -753,23 +753,23 @@ JSTempVector<T,N>::appendN(const T &t, size_t needed)
{
ReentrancyGuard g(*this);
if (usingInlineStorage()) {
size_t freespace = sInlineCapacity - inlineSize();
size_t freespace = sInlineCapacity - inlineLength();
if (needed <= freespace) {
Impl::copyConstructN(inlineEnd(), needed, t);
inlineSize() += needed;
inlineLength() += needed;
JS_ASSERT(usingInlineStorage());
return true;
}
if (!convertToHeapStorage(needed))
return false;
} else {
size_t freespace = heapCapacity() - heapSize();
size_t freespace = heapCapacity() - heapLength();
if (needed > freespace && !growHeapStorageBy(needed))
return false;
}
/* We are !usingInlineStorage(). Initialize new elements. */
JS_ASSERT(heapSize() <= heapCapacity() && heapCapacity() - heapSize() >= needed);
JS_ASSERT(heapLength() <= heapCapacity() && heapCapacity() - heapLength() >= needed);
Impl::copyConstructN(heapEnd(), needed, t);
heapEnd() += needed;
return true;
@ -783,23 +783,23 @@ JSTempVector<T,N>::append(const U *insBegin, const U *insEnd)
ReentrancyGuard g(*this);
size_t needed = JSUtils::PointerRangeSize(insBegin, insEnd);
if (usingInlineStorage()) {
size_t freespace = sInlineCapacity - inlineSize();
size_t freespace = sInlineCapacity - inlineLength();
if (needed <= freespace) {
Impl::copyConstruct(inlineEnd(), insBegin, insEnd);
inlineSize() += needed;
inlineLength() += needed;
JS_ASSERT(usingInlineStorage());
return true;
}
if (!convertToHeapStorage(needed))
return false;
} else {
size_t freespace = heapCapacity() - heapSize();
size_t freespace = heapCapacity() - heapLength();
if (needed > freespace && !growHeapStorageBy(needed))
return false;
}
/* We are !usingInlineStorage(). Initialize new elements. */
JS_ASSERT(heapSize() <= heapCapacity() && heapCapacity() - heapSize() >= needed);
JS_ASSERT(heapLength() <= heapCapacity() && heapCapacity() - heapLength() >= needed);
Impl::copyConstruct(heapEnd(), insBegin, insEnd);
heapEnd() += needed;
return true;
@ -820,7 +820,7 @@ JSTempVector<T,N>::popBack()
ReentrancyGuard g(*this);
JS_ASSERT(!empty());
if (usingInlineStorage()) {
--inlineSize();
--inlineLength();
inlineEnd()->~T();
} else {
--heapEnd();
@ -833,17 +833,17 @@ inline T *
JSTempVector<T,N>::extractRawBuffer()
{
if (usingInlineStorage()) {
T *ret = reinterpret_cast<T *>(mCx->malloc(inlineSize() * sizeof(T)));
T *ret = reinterpret_cast<T *>(mCx->malloc(inlineLength() * sizeof(T)));
if (!ret)
return NULL;
Impl::copyConstruct(ret, inlineBegin(), inlineEnd());
Impl::destroy(inlineBegin(), inlineEnd());
inlineSize() = 0;
inlineLength() = 0;
return ret;
}
T *ret = heapBegin();
mSizeOrCapacity = 0; /* marks us as !usingInlineStorage() */
mLengthOrCapacity = 0; /* marks us as !usingInlineStorage() */
return ret;
}
@ -856,7 +856,7 @@ JSTempVector<T,N>::replaceRawBuffer(T *p, size_t length)
/* Destroy what we have. */
if (usingInlineStorage()) {
Impl::destroy(inlineBegin(), inlineEnd());
inlineSize() = 0;
inlineLength() = 0;
} else {
Impl::destroy(heapBegin(), heapEnd());
mCx->free(heapBegin());
@ -865,15 +865,15 @@ JSTempVector<T,N>::replaceRawBuffer(T *p, size_t length)
/* Take in the new buffer. */
if (length <= sInlineCapacity) {
/*
* (mSizeOrCapacity <= sInlineCapacity) means inline storage, so we MUST
* use inline storage, even though p might otherwise be acceptable.
* (mLengthOrCapacity <= sInlineCapacity) means inline storage, so we
* MUST use inline storage, even though p might otherwise be acceptable.
*/
mSizeOrCapacity = length; /* marks us as usingInlineStorage() */
mLengthOrCapacity = length; /* marks us as usingInlineStorage() */
Impl::copyConstruct(inlineBegin(), p, p + length);
Impl::destroy(p, p + length);
mCx->free(p);
} else {
mSizeOrCapacity = length; /* marks us as !usingInlineStorage() */
mLengthOrCapacity = length; /* marks us as !usingInlineStorage() */
heapBegin() = p;
heapEnd() = heapBegin() + length;
}