зеркало из https://github.com/mozilla/gecko-dev.git
Detect some OOM conditions. b=602935, r=jorendorff.
This commit is contained in:
Родитель
051c03078f
Коммит
5dfc1b29e9
|
@ -2315,6 +2315,8 @@ ethogram_construct(JSContext *cx, uintN argc, jsval *vp)
|
|||
EthogramEventBuffer *p;
|
||||
|
||||
p = (EthogramEventBuffer *) JS_malloc(cx, sizeof(EthogramEventBuffer));
|
||||
if (!p)
|
||||
return JS_FALSE;
|
||||
|
||||
p->mReadPos = p->mWritePos = 0;
|
||||
p->mScripts = NULL;
|
||||
|
|
|
@ -328,201 +328,202 @@ js_dtobasestr(DtoaState *state, int base, double dinput)
|
|||
|
||||
dval(d) = dinput;
|
||||
buffer = (char*) js_malloc(DTOBASESTR_BUFFER_SIZE);
|
||||
if (buffer) {
|
||||
p = buffer;
|
||||
if (dval(d) < 0.0
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
p = buffer;
|
||||
|
||||
if (dval(d) < 0.0
|
||||
#if defined(XP_WIN) || defined(XP_OS2)
|
||||
&& !((word0(d) & Exp_mask) == Exp_mask && ((word0(d) & Frac_mask) || word1(d))) /* Visual C++ doesn't know how to compare against NaN */
|
||||
&& !((word0(d) & Exp_mask) == Exp_mask && ((word0(d) & Frac_mask) || word1(d))) /* Visual C++ doesn't know how to compare against NaN */
|
||||
#endif
|
||||
) {
|
||||
*p++ = '-';
|
||||
dval(d) = -dval(d);
|
||||
}
|
||||
) {
|
||||
*p++ = '-';
|
||||
dval(d) = -dval(d);
|
||||
}
|
||||
|
||||
/* Check for Infinity and NaN */
|
||||
if ((word0(d) & Exp_mask) == Exp_mask) {
|
||||
strcpy(p, !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN");
|
||||
return buffer;
|
||||
}
|
||||
/* Check for Infinity and NaN */
|
||||
if ((word0(d) & Exp_mask) == Exp_mask) {
|
||||
strcpy(p, !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Output the integer part of d with the digits in reverse order. */
|
||||
pInt = p;
|
||||
dval(di) = floor(dval(d));
|
||||
if (dval(di) <= 4294967295.0) {
|
||||
uint32 n = (uint32)dval(di);
|
||||
if (n)
|
||||
do {
|
||||
uint32 m = n / base;
|
||||
digit = n - m*base;
|
||||
n = m;
|
||||
JS_ASSERT(digit < (uint32)base);
|
||||
*p++ = BASEDIGIT(digit);
|
||||
} while (n);
|
||||
else *p++ = '0';
|
||||
} else {
|
||||
int e;
|
||||
int bits; /* Number of significant bits in di; not used. */
|
||||
Bigint *b = d2b(PASS_STATE di, &e, &bits);
|
||||
if (!b)
|
||||
goto nomem1;
|
||||
b = lshift(PASS_STATE b, e);
|
||||
if (!b) {
|
||||
nomem1:
|
||||
Bfree(PASS_STATE b);
|
||||
js_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
/* Output the integer part of d with the digits in reverse order. */
|
||||
pInt = p;
|
||||
dval(di) = floor(dval(d));
|
||||
if (dval(di) <= 4294967295.0) {
|
||||
uint32 n = (uint32)dval(di);
|
||||
if (n)
|
||||
do {
|
||||
digit = divrem(b, base);
|
||||
uint32 m = n / base;
|
||||
digit = n - m*base;
|
||||
n = m;
|
||||
JS_ASSERT(digit < (uint32)base);
|
||||
*p++ = BASEDIGIT(digit);
|
||||
} while (b->wds);
|
||||
} while (n);
|
||||
else *p++ = '0';
|
||||
} else {
|
||||
int e;
|
||||
int bits; /* Number of significant bits in di; not used. */
|
||||
Bigint *b = d2b(PASS_STATE di, &e, &bits);
|
||||
if (!b)
|
||||
goto nomem1;
|
||||
b = lshift(PASS_STATE b, e);
|
||||
if (!b) {
|
||||
nomem1:
|
||||
Bfree(PASS_STATE b);
|
||||
js_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
/* Reverse the digits of the integer part of d. */
|
||||
q = p-1;
|
||||
while (q > pInt) {
|
||||
char ch = *pInt;
|
||||
*pInt++ = *q;
|
||||
*q-- = ch;
|
||||
}
|
||||
do {
|
||||
digit = divrem(b, base);
|
||||
JS_ASSERT(digit < (uint32)base);
|
||||
*p++ = BASEDIGIT(digit);
|
||||
} while (b->wds);
|
||||
Bfree(PASS_STATE b);
|
||||
}
|
||||
/* Reverse the digits of the integer part of d. */
|
||||
q = p-1;
|
||||
while (q > pInt) {
|
||||
char ch = *pInt;
|
||||
*pInt++ = *q;
|
||||
*q-- = ch;
|
||||
}
|
||||
|
||||
dval(df) = dval(d) - dval(di);
|
||||
if (dval(df) != 0.0) {
|
||||
/* We have a fraction. */
|
||||
int e, bbits;
|
||||
int32 s2, done;
|
||||
Bigint *b, *s, *mlo, *mhi;
|
||||
dval(df) = dval(d) - dval(di);
|
||||
if (dval(df) != 0.0) {
|
||||
/* We have a fraction. */
|
||||
int e, bbits;
|
||||
int32 s2, done;
|
||||
Bigint *b, *s, *mlo, *mhi;
|
||||
|
||||
b = s = mlo = mhi = NULL;
|
||||
b = s = mlo = mhi = NULL;
|
||||
|
||||
*p++ = '.';
|
||||
b = d2b(PASS_STATE df, &e, &bbits);
|
||||
if (!b) {
|
||||
nomem2:
|
||||
Bfree(PASS_STATE b);
|
||||
Bfree(PASS_STATE s);
|
||||
if (mlo != mhi)
|
||||
Bfree(PASS_STATE mlo);
|
||||
Bfree(PASS_STATE mhi);
|
||||
js_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
JS_ASSERT(e < 0);
|
||||
/* At this point df = b * 2^e. e must be less than zero because 0 < df < 1. */
|
||||
|
||||
s2 = -(int32)(word0(d) >> Exp_shift1 & Exp_mask>>Exp_shift1);
|
||||
#ifndef Sudden_Underflow
|
||||
if (!s2)
|
||||
s2 = -1;
|
||||
#endif
|
||||
s2 += Bias + P;
|
||||
/* 1/2^s2 = (nextDouble(d) - d)/2 */
|
||||
JS_ASSERT(-s2 < e);
|
||||
mlo = i2b(PASS_STATE 1);
|
||||
if (!mlo)
|
||||
goto nomem2;
|
||||
mhi = mlo;
|
||||
if (!word1(d) && !(word0(d) & Bndry_mask)
|
||||
#ifndef Sudden_Underflow
|
||||
&& word0(d) & (Exp_mask & Exp_mask << 1)
|
||||
#endif
|
||||
) {
|
||||
/* The special case. Here we want to be within a quarter of the last input
|
||||
significant digit instead of one half of it when the output string's value is less than d. */
|
||||
s2 += Log2P;
|
||||
mhi = i2b(PASS_STATE 1<<Log2P);
|
||||
if (!mhi)
|
||||
goto nomem2;
|
||||
}
|
||||
b = lshift(PASS_STATE b, e + s2);
|
||||
if (!b)
|
||||
goto nomem2;
|
||||
s = i2b(PASS_STATE 1);
|
||||
if (!s)
|
||||
goto nomem2;
|
||||
s = lshift(PASS_STATE s, s2);
|
||||
if (!s)
|
||||
goto nomem2;
|
||||
/* At this point we have the following:
|
||||
* s = 2^s2;
|
||||
* 1 > df = b/2^s2 > 0;
|
||||
* (d - prevDouble(d))/2 = mlo/2^s2;
|
||||
* (nextDouble(d) - d)/2 = mhi/2^s2. */
|
||||
|
||||
done = JS_FALSE;
|
||||
do {
|
||||
int32 j, j1;
|
||||
Bigint *delta;
|
||||
|
||||
b = multadd(PASS_STATE b, base, 0);
|
||||
if (!b)
|
||||
goto nomem2;
|
||||
digit = quorem2(b, s2);
|
||||
if (mlo == mhi) {
|
||||
mlo = mhi = multadd(PASS_STATE mlo, base, 0);
|
||||
if (!mhi)
|
||||
goto nomem2;
|
||||
}
|
||||
else {
|
||||
mlo = multadd(PASS_STATE mlo, base, 0);
|
||||
if (!mlo)
|
||||
goto nomem2;
|
||||
mhi = multadd(PASS_STATE mhi, base, 0);
|
||||
if (!mhi)
|
||||
goto nomem2;
|
||||
}
|
||||
|
||||
/* Do we yet have the shortest string that will round to d? */
|
||||
j = cmp(b, mlo);
|
||||
/* j is b/2^s2 compared with mlo/2^s2. */
|
||||
delta = diff(PASS_STATE s, mhi);
|
||||
if (!delta)
|
||||
goto nomem2;
|
||||
j1 = delta->sign ? 1 : cmp(b, delta);
|
||||
Bfree(PASS_STATE delta);
|
||||
/* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
|
||||
|
||||
#ifndef ROUND_BIASED
|
||||
if (j1 == 0 && !(word1(d) & 1)) {
|
||||
if (j > 0)
|
||||
digit++;
|
||||
done = JS_TRUE;
|
||||
} else
|
||||
#endif
|
||||
if (j < 0 || (j == 0
|
||||
#ifndef ROUND_BIASED
|
||||
&& !(word1(d) & 1)
|
||||
#endif
|
||||
)) {
|
||||
if (j1 > 0) {
|
||||
/* Either dig or dig+1 would work here as the least significant digit.
|
||||
Use whichever would produce an output value closer to d. */
|
||||
b = lshift(PASS_STATE b, 1);
|
||||
if (!b)
|
||||
goto nomem2;
|
||||
j1 = cmp(b, s);
|
||||
if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output
|
||||
* such as 3.5 in base 3. */
|
||||
digit++;
|
||||
}
|
||||
done = JS_TRUE;
|
||||
} else if (j1 > 0) {
|
||||
digit++;
|
||||
done = JS_TRUE;
|
||||
}
|
||||
JS_ASSERT(digit < (uint32)base);
|
||||
*p++ = BASEDIGIT(digit);
|
||||
} while (!done);
|
||||
*p++ = '.';
|
||||
b = d2b(PASS_STATE df, &e, &bbits);
|
||||
if (!b) {
|
||||
nomem2:
|
||||
Bfree(PASS_STATE b);
|
||||
Bfree(PASS_STATE s);
|
||||
if (mlo != mhi)
|
||||
Bfree(PASS_STATE mlo);
|
||||
Bfree(PASS_STATE mhi);
|
||||
js_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
JS_ASSERT(p < buffer + DTOBASESTR_BUFFER_SIZE);
|
||||
*p = '\0';
|
||||
JS_ASSERT(e < 0);
|
||||
/* At this point df = b * 2^e. e must be less than zero because 0 < df < 1. */
|
||||
|
||||
s2 = -(int32)(word0(d) >> Exp_shift1 & Exp_mask>>Exp_shift1);
|
||||
#ifndef Sudden_Underflow
|
||||
if (!s2)
|
||||
s2 = -1;
|
||||
#endif
|
||||
s2 += Bias + P;
|
||||
/* 1/2^s2 = (nextDouble(d) - d)/2 */
|
||||
JS_ASSERT(-s2 < e);
|
||||
mlo = i2b(PASS_STATE 1);
|
||||
if (!mlo)
|
||||
goto nomem2;
|
||||
mhi = mlo;
|
||||
if (!word1(d) && !(word0(d) & Bndry_mask)
|
||||
#ifndef Sudden_Underflow
|
||||
&& word0(d) & (Exp_mask & Exp_mask << 1)
|
||||
#endif
|
||||
) {
|
||||
/* The special case. Here we want to be within a quarter of the last input
|
||||
significant digit instead of one half of it when the output string's value is less than d. */
|
||||
s2 += Log2P;
|
||||
mhi = i2b(PASS_STATE 1<<Log2P);
|
||||
if (!mhi)
|
||||
goto nomem2;
|
||||
}
|
||||
b = lshift(PASS_STATE b, e + s2);
|
||||
if (!b)
|
||||
goto nomem2;
|
||||
s = i2b(PASS_STATE 1);
|
||||
if (!s)
|
||||
goto nomem2;
|
||||
s = lshift(PASS_STATE s, s2);
|
||||
if (!s)
|
||||
goto nomem2;
|
||||
/* At this point we have the following:
|
||||
* s = 2^s2;
|
||||
* 1 > df = b/2^s2 > 0;
|
||||
* (d - prevDouble(d))/2 = mlo/2^s2;
|
||||
* (nextDouble(d) - d)/2 = mhi/2^s2. */
|
||||
|
||||
done = JS_FALSE;
|
||||
do {
|
||||
int32 j, j1;
|
||||
Bigint *delta;
|
||||
|
||||
b = multadd(PASS_STATE b, base, 0);
|
||||
if (!b)
|
||||
goto nomem2;
|
||||
digit = quorem2(b, s2);
|
||||
if (mlo == mhi) {
|
||||
mlo = mhi = multadd(PASS_STATE mlo, base, 0);
|
||||
if (!mhi)
|
||||
goto nomem2;
|
||||
}
|
||||
else {
|
||||
mlo = multadd(PASS_STATE mlo, base, 0);
|
||||
if (!mlo)
|
||||
goto nomem2;
|
||||
mhi = multadd(PASS_STATE mhi, base, 0);
|
||||
if (!mhi)
|
||||
goto nomem2;
|
||||
}
|
||||
|
||||
/* Do we yet have the shortest string that will round to d? */
|
||||
j = cmp(b, mlo);
|
||||
/* j is b/2^s2 compared with mlo/2^s2. */
|
||||
delta = diff(PASS_STATE s, mhi);
|
||||
if (!delta)
|
||||
goto nomem2;
|
||||
j1 = delta->sign ? 1 : cmp(b, delta);
|
||||
Bfree(PASS_STATE delta);
|
||||
/* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
|
||||
|
||||
#ifndef ROUND_BIASED
|
||||
if (j1 == 0 && !(word1(d) & 1)) {
|
||||
if (j > 0)
|
||||
digit++;
|
||||
done = JS_TRUE;
|
||||
} else
|
||||
#endif
|
||||
if (j < 0 || (j == 0
|
||||
#ifndef ROUND_BIASED
|
||||
&& !(word1(d) & 1)
|
||||
#endif
|
||||
)) {
|
||||
if (j1 > 0) {
|
||||
/* Either dig or dig+1 would work here as the least significant digit.
|
||||
Use whichever would produce an output value closer to d. */
|
||||
b = lshift(PASS_STATE b, 1);
|
||||
if (!b)
|
||||
goto nomem2;
|
||||
j1 = cmp(b, s);
|
||||
if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output
|
||||
* such as 3.5 in base 3. */
|
||||
digit++;
|
||||
}
|
||||
done = JS_TRUE;
|
||||
} else if (j1 > 0) {
|
||||
digit++;
|
||||
done = JS_TRUE;
|
||||
}
|
||||
JS_ASSERT(digit < (uint32)base);
|
||||
*p++ = BASEDIGIT(digit);
|
||||
} while (!done);
|
||||
Bfree(PASS_STATE b);
|
||||
Bfree(PASS_STATE s);
|
||||
if (mlo != mhi)
|
||||
Bfree(PASS_STATE mlo);
|
||||
Bfree(PASS_STATE mhi);
|
||||
}
|
||||
JS_ASSERT(p < buffer + DTOBASESTR_BUFFER_SIZE);
|
||||
*p = '\0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
|
@ -1657,6 +1657,8 @@ js_DumpOpMeters()
|
|||
# define SIGNIFICANT(count,total) (200. * (count) >= (total))
|
||||
|
||||
graph = (Edge *) js_calloc(nedges * sizeof graph[0]);
|
||||
if (!graph)
|
||||
return;
|
||||
for (i = nedges = 0; i < JSOP_LIMIT; i++) {
|
||||
from = js_CodeName[i];
|
||||
for (j = 0; j < JSOP_LIMIT; j++) {
|
||||
|
|
|
@ -404,20 +404,6 @@ js_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
|
|||
return FinishConcat(cx, leftRopeTop, rightRopeTop, left, right, length, buf);
|
||||
}
|
||||
|
||||
JSString * JS_FASTCALL
|
||||
js_ConcatStringsZ(JSContext *cx, const char *left, JSString *right)
|
||||
{
|
||||
const size_t leftLength = strlen(left);
|
||||
const size_t newLength = leftLength + right->length();
|
||||
const size_t newSize = (newLength + 1) * sizeof(jschar);
|
||||
jschar *chars = static_cast<jschar *>(cx->malloc(newSize));
|
||||
for (size_t i = 0; i < leftLength; ++i)
|
||||
chars[i] = left[i];
|
||||
js_strncpy(chars + leftLength, right->chars(), right->length());
|
||||
JSString *str = js_NewString(cx, chars, newLength);
|
||||
return str;
|
||||
}
|
||||
|
||||
const jschar *
|
||||
JSString::undepend(JSContext *cx)
|
||||
{
|
||||
|
|
|
@ -76,9 +76,6 @@ js_GetDependentStringChars(JSString *str);
|
|||
extern JSString * JS_FASTCALL
|
||||
js_ConcatStrings(JSContext *cx, JSString *left, JSString *right);
|
||||
|
||||
extern JSString * JS_FASTCALL
|
||||
js_ConcatStringsZ(JSContext *cx, const char *left, JSString *right);
|
||||
|
||||
JS_STATIC_ASSERT(JS_BITS_PER_WORD >= 32);
|
||||
|
||||
struct JSRopeBufferInfo {
|
||||
|
|
|
@ -4594,10 +4594,12 @@ TraceRecorder::compile()
|
|||
/* Associate a filename and line number with the fragment. */
|
||||
const char* filename = cx->fp()->script()->filename;
|
||||
char* label = (char*)js_malloc((filename ? strlen(filename) : 7) + 16);
|
||||
sprintf(label, "%s:%u", filename ? filename : "<stdin>",
|
||||
js_FramePCToLineNumber(cx, cx->fp()));
|
||||
lirbuf->printer->addrNameMap->addAddrRange(fragment, sizeof(Fragment), 0, label);
|
||||
js_free(label);
|
||||
if (label) {
|
||||
sprintf(label, "%s:%u", filename ? filename : "<stdin>",
|
||||
js_FramePCToLineNumber(cx, cx->fp()));
|
||||
lirbuf->printer->addrNameMap->addAddrRange(fragment, sizeof(Fragment), 0, label);
|
||||
js_free(label);
|
||||
}
|
||||
#endif
|
||||
|
||||
Assembler *assm = traceMonitor->assembler;
|
||||
|
|
|
@ -927,7 +927,8 @@ class TypedArrayTemplate
|
|||
return false;
|
||||
}
|
||||
|
||||
tarray->copyFrom(src, offset);
|
||||
if (!tarray->copyFrom(cx, src, offset))
|
||||
return false;
|
||||
} else if (arg0->wrappedObject(cx)->isArray()) {
|
||||
jsuint len;
|
||||
if (!js_GetLengthProperty(cx, arg0, &len))
|
||||
|
@ -1007,7 +1008,8 @@ class TypedArrayTemplate
|
|||
|
||||
if (!createBufferWithSizeAndCount(cx, sizeof(NativeType), tarray->length))
|
||||
return false;
|
||||
copyFrom(tarray);
|
||||
if (!copyFrom(cx, tarray))
|
||||
return false;
|
||||
} else if (other->getClass() == &ArrayBuffer::jsclass) {
|
||||
ArrayBuffer *abuf = ArrayBuffer::fromJSObject(other);
|
||||
|
||||
|
@ -1154,21 +1156,19 @@ class TypedArrayTemplate
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
copyFrom(TypedArray *tarray, jsuint offset = 0)
|
||||
bool
|
||||
copyFrom(JSContext *cx, TypedArray *tarray, jsuint offset = 0)
|
||||
{
|
||||
JS_ASSERT(offset <= length);
|
||||
JS_ASSERT(tarray->length <= length - offset);
|
||||
if (tarray->buffer == buffer) {
|
||||
copyFromWithOverlap(tarray, offset);
|
||||
return;
|
||||
}
|
||||
if (tarray->buffer == buffer)
|
||||
return copyFromWithOverlap(cx, tarray, offset);
|
||||
|
||||
NativeType *dest = static_cast<NativeType*>(data) + offset;
|
||||
|
||||
if (tarray->type == type) {
|
||||
memcpy(dest, tarray->data, tarray->byteLength);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
uintN srclen = tarray->length;
|
||||
|
@ -1226,10 +1226,12 @@ class TypedArrayTemplate
|
|||
JS_NOT_REACHED("copyFrom with a TypedArray of unknown type");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
copyFromWithOverlap(TypedArray *tarray, jsuint offset = 0)
|
||||
bool
|
||||
copyFromWithOverlap(JSContext *cx, TypedArray *tarray, jsuint offset = 0)
|
||||
{
|
||||
JS_ASSERT(offset < length);
|
||||
|
||||
|
@ -1237,12 +1239,16 @@ class TypedArrayTemplate
|
|||
|
||||
if (tarray->type == type) {
|
||||
memmove(dest, tarray->data, tarray->byteLength);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We have to make a copy of the source array here, since
|
||||
// there's overlap, and we have to convert types.
|
||||
void *srcbuf = js_malloc(tarray->byteLength);
|
||||
if (!srcbuf) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
memcpy(srcbuf, tarray->data, tarray->byteLength);
|
||||
|
||||
switch (tarray->type) {
|
||||
|
@ -1301,6 +1307,7 @@ class TypedArrayTemplate
|
|||
}
|
||||
|
||||
js_free(srcbuf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
Загрузка…
Ссылка в новой задаче