mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 834242 - Reduce cost of exact stack rooting during property reads, r=terrence.
This commit is contained in:
parent
c511765584
commit
ca7794f586
@ -730,7 +730,7 @@ HashableValue::setValue(JSContext *cx, const Value &v)
|
||||
{
|
||||
if (v.isString()) {
|
||||
// Atomize so that hash() and equals() are fast and infallible.
|
||||
JSString *str = AtomizeString(cx, v.toString(), DoNotInternAtom);
|
||||
JSString *str = AtomizeString<CanGC>(cx, v.toString(), DoNotInternAtom);
|
||||
if (!str)
|
||||
return false;
|
||||
value = StringValue(str);
|
||||
|
@ -124,7 +124,7 @@ obj_toSource(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (!detector.init())
|
||||
return false;
|
||||
if (detector.foundCycle()) {
|
||||
JSString *str = js_NewStringCopyZ(cx, "{}");
|
||||
JSString *str = js_NewStringCopyZ<CanGC>(cx, "{}");
|
||||
if (!str)
|
||||
return false;
|
||||
args.rval().setString(str);
|
||||
@ -763,7 +763,7 @@ obj_keys(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (JSID_IS_STRING(id)) {
|
||||
vals.infallibleAppend(StringValue(JSID_TO_STRING(id)));
|
||||
} else if (JSID_IS_INT(id)) {
|
||||
JSString *str = Int32ToString(cx, JSID_TO_INT(id));
|
||||
JSString *str = Int32ToString<CanGC>(cx, JSID_TO_INT(id));
|
||||
if (!str)
|
||||
return false;
|
||||
vals.infallibleAppend(StringValue(str));
|
||||
@ -799,7 +799,7 @@ obj_getOwnPropertyNames(JSContext *cx, unsigned argc, Value *vp)
|
||||
for (size_t i = 0, len = keys.length(); i < len; i++) {
|
||||
jsid id = keys[i];
|
||||
if (JSID_IS_INT(id)) {
|
||||
JSString *str = Int32ToString(cx, JSID_TO_INT(id));
|
||||
JSString *str = Int32ToString<CanGC>(cx, JSID_TO_INT(id));
|
||||
if (!str)
|
||||
return false;
|
||||
vals[i].setString(str);
|
||||
|
@ -1832,7 +1832,7 @@ ParallelArrayObject::getGeneric(JSContext *cx, HandleObject obj, HandleObject re
|
||||
if (ValueIsSpecial(obj, &idval, &sid, cx))
|
||||
return getSpecial(cx, obj, receiver, sid, vp);
|
||||
|
||||
JSAtom *atom = ToAtom(cx, idval);
|
||||
JSAtom *atom = ToAtom<CanGC>(cx, idval);
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
|
@ -70,7 +70,7 @@ js::CreateRegExpMatchResult(JSContext *cx, JSString *input_, StableCharPtr chars
|
||||
return false;
|
||||
|
||||
if (!input) {
|
||||
input = js_NewStringCopyN(cx, chars.get(), length);
|
||||
input = js_NewStringCopyN<CanGC>(cx, chars.get(), length);
|
||||
if (!input)
|
||||
return false;
|
||||
}
|
||||
@ -285,7 +285,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
source = AtomizeString(cx, str);
|
||||
source = AtomizeString<CanGC>(cx, str);
|
||||
if (!source)
|
||||
return false;
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, AbstractFramePtr
|
||||
* Save eval program source in script->atoms[0] for the
|
||||
* eval cache (see EvalCacheLookup in jsobj.cpp).
|
||||
*/
|
||||
JSAtom *atom = AtomizeString(cx, source);
|
||||
JSAtom *atom = AtomizeString<CanGC>(cx, source);
|
||||
jsatomid _;
|
||||
if (!atom || !bce.makeAtomIndex(atom, &_))
|
||||
return UnrootedScript(NULL);
|
||||
|
@ -87,10 +87,10 @@ FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
|
||||
|
||||
case PNK_STRING:
|
||||
if (pn->isKind(PNK_NUMBER)) {
|
||||
JSString *str = js_NumberToString(cx, pn->pn_dval);
|
||||
JSString *str = js_NumberToString<CanGC>(cx, pn->pn_dval);
|
||||
if (!str)
|
||||
return false;
|
||||
pn->pn_atom = AtomizeString(cx, str);
|
||||
pn->pn_atom = AtomizeString<CanGC>(cx, str);
|
||||
if (!pn->pn_atom)
|
||||
return false;
|
||||
pn->setKind(PNK_STRING);
|
||||
@ -288,7 +288,7 @@ FoldXMLConstants(JSContext *cx, ParseNode **pnp, Parser *parser)
|
||||
pn1->setKind(PNK_XMLTEXT);
|
||||
pn1->setOp(JSOP_STRING);
|
||||
pn1->setArity(PN_NULLARY);
|
||||
pn1->pn_atom = AtomizeString(cx, accum);
|
||||
pn1->pn_atom = AtomizeString<CanGC>(cx, accum);
|
||||
if (!pn1->pn_atom)
|
||||
return false;
|
||||
JS_ASSERT(listp != &pn1->pn_next);
|
||||
@ -340,7 +340,7 @@ FoldXMLConstants(JSContext *cx, ParseNode **pnp, Parser *parser)
|
||||
pn1->setKind(PNK_XMLTEXT);
|
||||
pn1->setOp(JSOP_STRING);
|
||||
pn1->setArity(PN_NULLARY);
|
||||
pn1->pn_atom = AtomizeString(cx, accum);
|
||||
pn1->pn_atom = AtomizeString<CanGC>(cx, accum);
|
||||
if (!pn1->pn_atom)
|
||||
return false;
|
||||
JS_ASSERT(listp != &pn1->pn_next);
|
||||
@ -710,7 +710,7 @@ frontend::FoldConstants(JSContext *cx, ParseNode **pnp, Parser *parser, bool inG
|
||||
if (!chars)
|
||||
return false;
|
||||
chars[length] = 0;
|
||||
JSString *str = js_NewString(cx, chars, length);
|
||||
JSString *str = js_NewString<CanGC>(cx, chars, length);
|
||||
if (!str) {
|
||||
js_free(chars);
|
||||
return false;
|
||||
@ -726,7 +726,7 @@ frontend::FoldConstants(JSContext *cx, ParseNode **pnp, Parser *parser, bool inG
|
||||
JS_ASSERT(*chars == 0);
|
||||
|
||||
/* Atomize the result string and mutate pn to refer to it. */
|
||||
pn->pn_atom = AtomizeString(cx, str);
|
||||
pn->pn_atom = AtomizeString<CanGC>(cx, str);
|
||||
if (!pn->pn_atom)
|
||||
return false;
|
||||
pn->setKind(PNK_STRING);
|
||||
@ -747,7 +747,7 @@ frontend::FoldConstants(JSContext *cx, ParseNode **pnp, Parser *parser, bool inG
|
||||
RootedString str(cx, js_ConcatStrings(cx, left, right));
|
||||
if (!str)
|
||||
return false;
|
||||
pn->pn_atom = AtomizeString(cx, str);
|
||||
pn->pn_atom = AtomizeString<CanGC>(cx, str);
|
||||
if (!pn->pn_atom)
|
||||
return false;
|
||||
pn->setKind(PNK_STRING);
|
||||
|
@ -5636,7 +5636,7 @@ Parser::memberExpr(bool allowCallSyntax)
|
||||
} else if (propExpr->isKind(PNK_NUMBER)) {
|
||||
double number = propExpr->pn_dval;
|
||||
if (number != ToUint32(number)) {
|
||||
JSAtom *atom = ToAtom(context, DoubleValue(number));
|
||||
JSAtom *atom = ToAtom<CanGC>(context, DoubleValue(number));
|
||||
if (!atom)
|
||||
return NULL;
|
||||
name = atom->asPropertyName();
|
||||
@ -6651,7 +6651,7 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
|
||||
if (!pn3)
|
||||
return NULL;
|
||||
pn3->pn_dval = tokenStream.currentToken().number();
|
||||
atom = ToAtom(context, DoubleValue(pn3->pn_dval));
|
||||
atom = ToAtom<CanGC>(context, DoubleValue(pn3->pn_dval));
|
||||
if (!atom)
|
||||
return NULL;
|
||||
break;
|
||||
@ -6685,7 +6685,7 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
|
||||
if (!pn3)
|
||||
return NULL;
|
||||
pn3->pn_dval = index;
|
||||
atom = ToAtom(context, DoubleValue(pn3->pn_dval));
|
||||
atom = ToAtom<CanGC>(context, DoubleValue(pn3->pn_dval));
|
||||
if (!atom)
|
||||
return NULL;
|
||||
} else {
|
||||
@ -6698,7 +6698,7 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
|
||||
if (!pn3)
|
||||
return NULL;
|
||||
pn3->pn_dval = tokenStream.currentToken().number();
|
||||
atom = ToAtom(context, DoubleValue(pn3->pn_dval));
|
||||
atom = ToAtom<CanGC>(context, DoubleValue(pn3->pn_dval));
|
||||
if (!atom)
|
||||
return NULL;
|
||||
} else {
|
||||
|
@ -1056,8 +1056,8 @@ TokenStream::getXMLMarkup(TokenKind *ttp, Token **tpp)
|
||||
if (contentIndex < 0) {
|
||||
data = cx->names().empty;
|
||||
} else {
|
||||
data = AtomizeChars(cx, tokenbuf.begin() + contentIndex,
|
||||
tokenbuf.length() - contentIndex);
|
||||
data = AtomizeChars<CanGC>(cx, tokenbuf.begin() + contentIndex,
|
||||
tokenbuf.length() - contentIndex);
|
||||
if (!data)
|
||||
goto error;
|
||||
}
|
||||
@ -1284,7 +1284,7 @@ TokenStream::newToken(ptrdiff_t adjust)
|
||||
JS_ALWAYS_INLINE JSAtom *
|
||||
TokenStream::atomize(JSContext *cx, CharBuffer &cb)
|
||||
{
|
||||
return AtomizeChars(cx, cb.begin(), cb.length());
|
||||
return AtomizeChars<CanGC>(cx, cb.begin(), cb.length());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -1580,7 +1580,7 @@ TokenStream::getTokenInternal()
|
||||
*/
|
||||
JSAtom *atom;
|
||||
if (!hadUnicodeEscape)
|
||||
atom = AtomizeChars(cx, identStart, userbuf.addressOfNextRawChar() - identStart);
|
||||
atom = AtomizeChars<CanGC>(cx, identStart, userbuf.addressOfNextRawChar() - identStart);
|
||||
else
|
||||
atom = atomize(cx, tokenbuf);
|
||||
if (!atom)
|
||||
|
@ -861,6 +861,10 @@ class FakeMutableHandle : public js::MutableHandleBase<T>
|
||||
ptr = t;
|
||||
}
|
||||
|
||||
FakeMutableHandle(FakeRooted<T> *root) {
|
||||
ptr = root->address();
|
||||
}
|
||||
|
||||
void set(T v) {
|
||||
JS_ASSERT(!js::RootMethods<T>::poisoned(v));
|
||||
*ptr = v;
|
||||
@ -887,19 +891,19 @@ class FakeMutableHandle : public js::MutableHandleBase<T>
|
||||
* operate on either rooted or unrooted data.
|
||||
*
|
||||
* The toHandle() and toMutableHandle() functions are for calling functions
|
||||
* which require handle types and are only called in the ALLOW_GC case. These
|
||||
* which require handle types and are only called in the CanGC case. These
|
||||
* allow the calling code to type check.
|
||||
*/
|
||||
enum AllowGC {
|
||||
DONT_ALLOW_GC = 0,
|
||||
ALLOW_GC = 1
|
||||
NoGC = 0,
|
||||
CanGC = 1
|
||||
};
|
||||
template <typename T, AllowGC allowGC>
|
||||
class MaybeRooted
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T> class MaybeRooted<T, ALLOW_GC>
|
||||
template <typename T> class MaybeRooted<T, CanGC>
|
||||
{
|
||||
public:
|
||||
typedef Handle<T> HandleType;
|
||||
@ -915,7 +919,7 @@ template <typename T> class MaybeRooted<T, ALLOW_GC>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class MaybeRooted<T, DONT_ALLOW_GC>
|
||||
template <typename T> class MaybeRooted<T, NoGC>
|
||||
{
|
||||
public:
|
||||
typedef T HandleType;
|
||||
|
@ -397,7 +397,7 @@ CodeGenerator::visitPolyInlineDispatch(LPolyInlineDispatch *lir)
|
||||
|
||||
typedef JSFlatString *(*IntToStringFn)(JSContext *, int);
|
||||
static const VMFunction IntToStringInfo =
|
||||
FunctionInfo<IntToStringFn>(Int32ToString);
|
||||
FunctionInfo<IntToStringFn>(Int32ToString<CanGC>);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitIntToString(LIntToString *lir)
|
||||
@ -2403,7 +2403,7 @@ CodeGenerator::visitCompareS(LCompareS *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*CompareFn)(JSContext *, HandleValue, HandleValue, JSBool *);
|
||||
typedef bool (*CompareFn)(JSContext *, MutableHandleValue, MutableHandleValue, JSBool *);
|
||||
static const VMFunction EqInfo = FunctionInfo<CompareFn>(ion::LooselyEqual<true>);
|
||||
static const VMFunction NeInfo = FunctionInfo<CompareFn>(ion::LooselyEqual<false>);
|
||||
static const VMFunction StrictEqInfo = FunctionInfo<CompareFn>(ion::StrictlyEqual<true>);
|
||||
@ -3730,7 +3730,7 @@ CodeGenerator::visitCallGetProperty(LCallGetProperty *lir)
|
||||
return callVM(GetPropertyInfo, lir);
|
||||
}
|
||||
|
||||
typedef bool (*GetOrCallElementFn)(JSContext *, HandleValue, HandleValue, MutableHandleValue);
|
||||
typedef bool (*GetOrCallElementFn)(JSContext *, MutableHandleValue, HandleValue, MutableHandleValue);
|
||||
static const VMFunction GetElementInfo = FunctionInfo<GetOrCallElementFn>(js::GetElement);
|
||||
static const VMFunction CallElementInfo = FunctionInfo<GetOrCallElementFn>(js::CallElement);
|
||||
|
||||
@ -4505,7 +4505,7 @@ CodeGenerator::visitLoadTypedArrayElementHole(LLoadTypedArrayElementHole *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*GetElementMonitoredFn)(JSContext *, HandleValue, HandleValue, MutableHandleValue);
|
||||
typedef bool (*GetElementMonitoredFn)(JSContext *, MutableHandleValue, HandleValue, MutableHandleValue);
|
||||
static const VMFunction GetElementMonitoredInfo =
|
||||
FunctionInfo<GetElementMonitoredFn>(js::GetElementMonitored);
|
||||
|
||||
|
@ -323,7 +323,7 @@ IonCode::New(JSContext *cx, uint8_t *code, uint32_t bufferSize, JSC::ExecutableP
|
||||
{
|
||||
AssertCanGC();
|
||||
|
||||
IonCode *codeObj = gc::NewGCThing<IonCode, ALLOW_GC>(cx, gc::FINALIZE_IONCODE, sizeof(IonCode));
|
||||
IonCode *codeObj = gc::NewGCThing<IonCode, CanGC>(cx, gc::FINALIZE_IONCODE, sizeof(IonCode));
|
||||
if (!codeObj) {
|
||||
pool->release();
|
||||
return NULL;
|
||||
|
@ -1712,7 +1712,7 @@ js::ion::GetElementCache(JSContext *cx, size_t cacheIndex, HandleObject obj, Han
|
||||
RootedValue lval(cx, ObjectValue(*obj));
|
||||
|
||||
if (cache.isDisabled()) {
|
||||
if (!GetElementOperation(cx, JSOp(*pc), lval, idval, res))
|
||||
if (!GetElementOperation(cx, JSOp(*pc), &lval, idval, res))
|
||||
return false;
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
return true;
|
||||
@ -1747,7 +1747,7 @@ js::ion::GetElementCache(JSContext *cx, size_t cacheIndex, HandleObject obj, Han
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetElementOperation(cx, JSOp(*pc), lval, idval, res))
|
||||
if (!GetElementOperation(cx, JSOp(*pc), &lval, idval, res))
|
||||
return false;
|
||||
|
||||
// If no new attach was done, and we've reached maximum number of stubs, then
|
||||
|
@ -116,7 +116,7 @@ InvokeFunction(JSContext *cx, HandleFunction fun0, uint32_t argc, Value *argv, V
|
||||
JSObject *
|
||||
NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize)
|
||||
{
|
||||
return gc::NewGCThing<JSObject, ALLOW_GC>(cx, allocKind, thingSize);
|
||||
return gc::NewGCThing<JSObject, CanGC>(cx, allocKind, thingSize);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -167,7 +167,7 @@ InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue v
|
||||
|
||||
template<bool Equal>
|
||||
bool
|
||||
LooselyEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
LooselyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res)
|
||||
{
|
||||
bool equal;
|
||||
if (!js::LooselyEqual(cx, lhs, rhs, &equal))
|
||||
@ -176,12 +176,12 @@ LooselyEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool LooselyEqual<true>(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res);
|
||||
template bool LooselyEqual<false>(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res);
|
||||
template bool LooselyEqual<true>(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res);
|
||||
template bool LooselyEqual<false>(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res);
|
||||
|
||||
template<bool Equal>
|
||||
bool
|
||||
StrictlyEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
StrictlyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res)
|
||||
{
|
||||
bool equal;
|
||||
if (!js::StrictlyEqual(cx, lhs, rhs, &equal))
|
||||
@ -190,11 +190,11 @@ StrictlyEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool StrictlyEqual<true>(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res);
|
||||
template bool StrictlyEqual<false>(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res);
|
||||
template bool StrictlyEqual<true>(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res);
|
||||
template bool StrictlyEqual<false>(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res);
|
||||
|
||||
bool
|
||||
LessThan(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
LessThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res)
|
||||
{
|
||||
bool cond;
|
||||
if (!LessThanOperation(cx, lhs, rhs, &cond))
|
||||
@ -204,7 +204,7 @@ LessThan(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
}
|
||||
|
||||
bool
|
||||
LessThanOrEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
LessThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res)
|
||||
{
|
||||
bool cond;
|
||||
if (!LessThanOrEqualOperation(cx, lhs, rhs, &cond))
|
||||
@ -214,7 +214,7 @@ LessThanOrEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
}
|
||||
|
||||
bool
|
||||
GreaterThan(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
GreaterThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res)
|
||||
{
|
||||
bool cond;
|
||||
if (!GreaterThanOperation(cx, lhs, rhs, &cond))
|
||||
@ -224,7 +224,7 @@ GreaterThan(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
}
|
||||
|
||||
bool
|
||||
GreaterThanOrEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
|
||||
GreaterThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res)
|
||||
{
|
||||
bool cond;
|
||||
if (!GreaterThanOrEqualOperation(cx, lhs, rhs, &cond))
|
||||
@ -402,8 +402,7 @@ StringFromCharCode(JSContext *cx, int32_t code)
|
||||
if (StaticStrings::hasUnit(c))
|
||||
return cx->runtime->staticStrings.getUnit(c);
|
||||
|
||||
return js_NewStringCopyN(cx, &c, 1);
|
||||
|
||||
return js_NewStringCopyN<CanGC>(cx, &c, 1);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -419,15 +419,15 @@ bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleO
|
||||
bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value);
|
||||
|
||||
template<bool Equal>
|
||||
bool LooselyEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res);
|
||||
bool LooselyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res);
|
||||
|
||||
template<bool Equal>
|
||||
bool StrictlyEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res);
|
||||
bool StrictlyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res);
|
||||
|
||||
bool LessThan(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res);
|
||||
bool LessThanOrEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res);
|
||||
bool GreaterThan(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res);
|
||||
bool GreaterThanOrEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res);
|
||||
bool LessThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res);
|
||||
bool LessThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res);
|
||||
bool GreaterThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res);
|
||||
bool GreaterThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, JSBool *res);
|
||||
|
||||
template<bool Equal>
|
||||
bool StringsEqual(JSContext *cx, HandleString left, HandleString right, JSBool *res);
|
||||
|
@ -20,7 +20,7 @@ using mozilla::ArrayLength;
|
||||
template<size_t N> JSFlatString *
|
||||
NewString(JSContext *cx, const jschar (&chars)[N])
|
||||
{
|
||||
return js_NewStringCopyN(cx, chars, N);
|
||||
return js_NewStringCopyN<js::CanGC>(cx, chars, N);
|
||||
}
|
||||
|
||||
static const struct TestPair {
|
||||
|
@ -40,7 +40,7 @@ class AutoInflatedString {
|
||||
template<size_t N> JSFlatString *
|
||||
NewString(JSContext *cx, const jschar (&chars)[N])
|
||||
{
|
||||
return js_NewStringCopyN(cx, chars, N);
|
||||
return js_NewStringCopyN<CanGC>(cx, chars, N);
|
||||
}
|
||||
|
||||
BEGIN_TEST(testParseJSON_success)
|
||||
@ -60,7 +60,7 @@ BEGIN_TEST(testParseJSON_success)
|
||||
js::Rooted<JSFlatString*> str(cx);
|
||||
|
||||
const jschar emptystr[] = { '\0' };
|
||||
str = js_NewStringCopyN(cx, emptystr, 0);
|
||||
str = js_NewStringCopyN<CanGC>(cx, emptystr, 0);
|
||||
CHECK(str);
|
||||
CHECK(TryParse(cx, "\"\"", STRING_TO_JSVAL(str)));
|
||||
|
||||
|
@ -19,7 +19,7 @@ BEGIN_TEST(testStringBuffer_finishString)
|
||||
JSString *str = JS_NewStringCopyZ(cx, "foopy");
|
||||
CHECK(str);
|
||||
|
||||
js::Rooted<JSAtom*> atom(cx, js::AtomizeString(cx, str));
|
||||
js::Rooted<JSAtom*> atom(cx, js::AtomizeString<js::CanGC>(cx, str));
|
||||
CHECK(atom);
|
||||
|
||||
js::StringBuffer buffer(cx);
|
||||
|
@ -3623,7 +3623,7 @@ JS_PUBLIC_API(JSBool)
|
||||
JS_LookupUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, jsval *vp)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
return atom && JS_LookupPropertyById(cx, obj, AtomToId(atom), vp);
|
||||
}
|
||||
|
||||
@ -3696,7 +3696,7 @@ JS_PUBLIC_API(JSBool)
|
||||
JS_HasUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, JSBool *foundp)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
return atom && JS_HasPropertyById(cx, obj, AtomToId(atom), foundp);
|
||||
}
|
||||
|
||||
@ -3753,7 +3753,7 @@ JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *objArg, const jschar *name,
|
||||
JSBool *foundp)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
return atom && JS_AlreadyHasOwnPropertyById(cx, obj, AtomToId(atom), foundp);
|
||||
}
|
||||
|
||||
@ -3927,7 +3927,7 @@ DefineUCProperty(JSContext *cx, JSHandleObject obj, const jschar *name, size_t n
|
||||
{
|
||||
RootedValue value(cx, value_);
|
||||
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
if (!atom)
|
||||
return false;
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
@ -4130,7 +4130,7 @@ JS_GetUCPropertyAttributes(JSContext *cx, JSObject *objArg, const jschar *name,
|
||||
unsigned *attrsp, JSBool *foundp)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
|
||||
attrsp, foundp, NULL, NULL);
|
||||
}
|
||||
@ -4153,7 +4153,7 @@ JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *objArg,
|
||||
JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
|
||||
attrsp, foundp, getterp, setterp);
|
||||
}
|
||||
@ -4208,7 +4208,7 @@ JS_SetUCPropertyAttributes(JSContext *cx, JSObject *objArg, const jschar *name,
|
||||
unsigned attrs, JSBool *foundp)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
return atom && SetPropertyAttributesById(cx, obj, id, attrs, foundp);
|
||||
}
|
||||
@ -4320,7 +4320,7 @@ JS_PUBLIC_API(JSBool)
|
||||
JS_GetUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, jsval *vp)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
return atom && JS_GetPropertyById(cx, obj, AtomToId(atom), vp);
|
||||
}
|
||||
|
||||
@ -4399,7 +4399,7 @@ JS_PUBLIC_API(JSBool)
|
||||
JS_SetUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, jsval *vp)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
return atom && JS_SetPropertyById(cx, obj, AtomToId(atom), vp);
|
||||
}
|
||||
|
||||
@ -4472,7 +4472,7 @@ JS_DeleteUCProperty2(JSContext *cx, JSObject *objArg, const jschar *name, size_t
|
||||
assertSameCompartment(cx, obj);
|
||||
JSAutoResolveFlags rf(cx, 0);
|
||||
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
@ -5120,7 +5120,7 @@ JS_DefineUCFunction(JSContext *cx, JSObject *objArg,
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
if (!atom)
|
||||
return NULL;
|
||||
Rooted<jsid> id(cx, AtomToId(atom));
|
||||
@ -5543,7 +5543,7 @@ JS_DecompileScript(JSContext *cx, JSScript *scriptArg, const char *name, unsigne
|
||||
bool haveSource = script->scriptSource()->hasSourceData();
|
||||
if (!haveSource && !JSScript::loadSource(cx, script, &haveSource))
|
||||
return NULL;
|
||||
return haveSource ? script->sourceData(cx) : js_NewStringCopyZ(cx, "[no source]");
|
||||
return haveSource ? script->sourceData(cx) : js_NewStringCopyZ<CanGC>(cx, "[no source]");
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
@ -5935,7 +5935,7 @@ JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
return js_NewStringCopyN(cx, s, n);
|
||||
return js_NewStringCopyN<CanGC>(cx, s, n);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
@ -5953,7 +5953,7 @@ JS_NewStringCopyZ(JSContext *cx, const char *s)
|
||||
js = InflateString(cx, s, &n);
|
||||
if (!js)
|
||||
return NULL;
|
||||
str = js_NewString(cx, js, n);
|
||||
str = js_NewString<CanGC>(cx, js, n);
|
||||
if (!str)
|
||||
js_free(js);
|
||||
return str;
|
||||
@ -5985,7 +5985,7 @@ JS_InternJSString(JSContext *cx, JSString *str)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
JSAtom *atom = AtomizeString(cx, str, InternAtom);
|
||||
JSAtom *atom = AtomizeString<CanGC>(cx, str, InternAtom);
|
||||
JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
|
||||
return atom;
|
||||
}
|
||||
@ -6011,7 +6011,7 @@ JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
return js_NewString(cx, chars, length);
|
||||
return js_NewString<CanGC>(cx, chars, length);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
@ -6019,7 +6019,7 @@ JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
return js_NewStringCopyN(cx, s, n);
|
||||
return js_NewStringCopyN<CanGC>(cx, s, n);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
@ -6029,7 +6029,7 @@ JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
|
||||
CHECK_REQUEST(cx);
|
||||
if (!s)
|
||||
return cx->runtime->emptyString;
|
||||
return js_NewStringCopyZ(cx, s);
|
||||
return js_NewStringCopyZ<CanGC>(cx, s);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
@ -6037,7 +6037,7 @@ JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
JSAtom *atom = AtomizeChars(cx, s, length, InternAtom);
|
||||
JSAtom *atom = AtomizeChars<CanGC>(cx, s, length, InternAtom);
|
||||
JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
|
||||
return atom;
|
||||
}
|
||||
@ -6193,7 +6193,7 @@ JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
return js_NewString(cx, chars, length);
|
||||
return js_NewString<CanGC>(cx, chars, length);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
|
@ -270,7 +270,7 @@ AtomizeAndTakeOwnership(JSContext *cx, StableCharPtr tbchars, size_t length,
|
||||
|
||||
AutoEnterAtomsCompartment ac(cx);
|
||||
|
||||
UnrootedFlatString flat = js_NewString(cx, const_cast<jschar*>(tbchars.get()), length);
|
||||
UnrootedFlatString flat = js_NewString<CanGC>(cx, const_cast<jschar*>(tbchars.get()), length);
|
||||
if (!flat) {
|
||||
js_free((void*)tbchars.get());
|
||||
return UnrootedAtom();
|
||||
@ -287,6 +287,7 @@ AtomizeAndTakeOwnership(JSContext *cx, StableCharPtr tbchars, size_t length,
|
||||
}
|
||||
|
||||
/* |tbchars| must not point into an inline or short string. */
|
||||
template <AllowGC allowGC>
|
||||
JS_ALWAYS_INLINE
|
||||
static UnrootedAtom
|
||||
AtomizeAndCopyStableChars(JSContext *cx, const jschar *tbchars, size_t length, InternBehavior ib)
|
||||
@ -311,7 +312,7 @@ AtomizeAndCopyStableChars(JSContext *cx, const jschar *tbchars, size_t length, I
|
||||
|
||||
AutoEnterAtomsCompartment ac(cx);
|
||||
|
||||
UnrootedFlatString flat = js_NewStringCopyN(cx, tbchars, length);
|
||||
UnrootedFlatString flat = js_NewStringCopyN<allowGC>(cx, tbchars, length);
|
||||
if (!flat)
|
||||
return UnrootedAtom();
|
||||
|
||||
@ -325,6 +326,7 @@ AtomizeAndCopyStableChars(JSContext *cx, const jschar *tbchars, size_t length, I
|
||||
return atom;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
UnrootedAtom
|
||||
js::AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib /* = js::DoNotInternAtom */)
|
||||
{
|
||||
@ -344,14 +346,30 @@ js::AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib /* = js::D
|
||||
return &atom;
|
||||
}
|
||||
|
||||
const jschar *chars = str->getChars(cx);
|
||||
if (!chars)
|
||||
return NULL;
|
||||
|
||||
if (JSAtom *atom = AtomizeAndCopyStableChars<NoGC>(cx, chars, str->length(), ib))
|
||||
return atom;
|
||||
|
||||
if (!allowGC)
|
||||
return NULL;
|
||||
|
||||
JSStableString *stable = str->ensureStable(cx);
|
||||
if (!stable)
|
||||
return NULL;
|
||||
|
||||
JS_ASSERT(stable->length() <= JSString::MAX_LENGTH);
|
||||
return AtomizeAndCopyStableChars(cx, stable->chars().get(), stable->length(), ib);
|
||||
return AtomizeAndCopyStableChars<CanGC>(cx, stable->chars().get(), stable->length(), ib);
|
||||
}
|
||||
|
||||
template UnrootedAtom
|
||||
js::AtomizeString<CanGC>(JSContext *cx, JSString *str, js::InternBehavior ib);
|
||||
|
||||
template UnrootedAtom
|
||||
js::AtomizeString<NoGC>(JSContext *cx, JSString *str, js::InternBehavior ib);
|
||||
|
||||
UnrootedAtom
|
||||
js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib)
|
||||
{
|
||||
@ -374,7 +392,7 @@ js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib)
|
||||
jschar inflated[ATOMIZE_BUF_MAX];
|
||||
size_t inflatedLength = ATOMIZE_BUF_MAX - 1;
|
||||
InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength);
|
||||
atom = AtomizeAndCopyStableChars(cx, inflated, inflatedLength, ib);
|
||||
atom = AtomizeAndCopyStableChars<CanGC>(cx, inflated, inflatedLength, ib);
|
||||
} else {
|
||||
jschar *tbcharsZ = InflateString(cx, bytes, &length);
|
||||
if (!tbcharsZ)
|
||||
@ -385,20 +403,28 @@ js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib)
|
||||
return atom;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
UnrootedAtom
|
||||
js::AtomizeChars(JSContext *cx, const jschar *chars, size_t length, InternBehavior ib)
|
||||
{
|
||||
AssertCanGC();
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
if (!JSString::validateLength(cx, length))
|
||||
return NULL;
|
||||
|
||||
return AtomizeAndCopyStableChars(cx, chars, length, ib);
|
||||
return AtomizeAndCopyStableChars<allowGC>(cx, chars, length, ib);
|
||||
}
|
||||
|
||||
template UnrootedAtom
|
||||
js::AtomizeChars<CanGC>(JSContext *cx, const jschar *chars, size_t length, InternBehavior ib);
|
||||
|
||||
template UnrootedAtom
|
||||
js::AtomizeChars<NoGC>(JSContext *cx, const jschar *chars, size_t length, InternBehavior ib);
|
||||
|
||||
template <AllowGC allowGC>
|
||||
bool
|
||||
js::IndexToIdSlow(JSContext *cx, uint32_t index, MutableHandleId idp)
|
||||
js::IndexToIdSlow(JSContext *cx, uint32_t index,
|
||||
typename MaybeRooted<jsid, allowGC>::MutableHandleType idp)
|
||||
{
|
||||
JS_ASSERT(index > JSID_INT_MAX);
|
||||
|
||||
@ -406,7 +432,7 @@ js::IndexToIdSlow(JSContext *cx, uint32_t index, MutableHandleId idp)
|
||||
RangedPtr<jschar> end(ArrayEnd(buf), buf, ArrayEnd(buf));
|
||||
RangedPtr<jschar> start = BackfillIndexInCharBuffer(index, end);
|
||||
|
||||
JSAtom *atom = AtomizeChars(cx, start.get(), end - start);
|
||||
JSAtom *atom = AtomizeChars<allowGC>(cx, start.get(), end - start);
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
@ -414,6 +440,12 @@ js::IndexToIdSlow(JSContext *cx, uint32_t index, MutableHandleId idp)
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool
|
||||
js::IndexToIdSlow<CanGC>(JSContext *cx, uint32_t index, MutableHandleId idp);
|
||||
|
||||
template bool
|
||||
js::IndexToIdSlow<NoGC>(JSContext *cx, uint32_t index, FakeMutableHandle<jsid> idp);
|
||||
|
||||
bool
|
||||
js::InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval,
|
||||
MutableHandleId idp, MutableHandleValue vp)
|
||||
@ -441,7 +473,7 @@ js::InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval,
|
||||
}
|
||||
#endif
|
||||
|
||||
JSAtom *atom = ToAtom(cx, idval);
|
||||
JSAtom *atom = ToAtom<CanGC>(cx, idval);
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
@ -477,7 +509,7 @@ js::XDRAtom(XDRState<mode> *xdr, MutableHandleAtom atomp)
|
||||
#if IS_LITTLE_ENDIAN
|
||||
/* Directly access the little endian chars in the XDR buffer. */
|
||||
const jschar *chars = reinterpret_cast<const jschar *>(xdr->buf.read(nchars * sizeof(jschar)));
|
||||
atom = AtomizeChars(cx, chars, nchars);
|
||||
atom = AtomizeChars<CanGC>(cx, chars, nchars);
|
||||
#else
|
||||
/*
|
||||
* We must copy chars to a temporary buffer to convert between little and
|
||||
|
@ -226,13 +226,16 @@ extern UnrootedAtom
|
||||
Atomize(JSContext *cx, const char *bytes, size_t length,
|
||||
js::InternBehavior ib = js::DoNotInternAtom);
|
||||
|
||||
template <AllowGC allowGC>
|
||||
extern UnrootedAtom
|
||||
AtomizeChars(JSContext *cx, const jschar *chars, size_t length,
|
||||
js::InternBehavior ib = js::DoNotInternAtom);
|
||||
|
||||
template <AllowGC allowGC>
|
||||
extern UnrootedAtom
|
||||
AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib = js::DoNotInternAtom);
|
||||
|
||||
template <AllowGC allowGC>
|
||||
inline JSAtom *
|
||||
ToAtom(JSContext *cx, const js::Value &v);
|
||||
|
||||
|
@ -28,15 +28,16 @@ js::AtomStateEntry::asPtr() const
|
||||
|
||||
namespace js {
|
||||
|
||||
template <AllowGC allowGC>
|
||||
inline JSAtom *
|
||||
ToAtom(JSContext *cx, const js::Value &v)
|
||||
{
|
||||
if (!v.isString()) {
|
||||
JSString *str = js::ToStringSlow(cx, v);
|
||||
JSString *str = js::ToStringSlow<allowGC>(cx, v);
|
||||
if (!str)
|
||||
return NULL;
|
||||
JS::Anchor<JSString *> anchor(str);
|
||||
return AtomizeString(cx, str);
|
||||
return AtomizeString<allowGC>(cx, str);
|
||||
}
|
||||
|
||||
JSString *str = v.toString();
|
||||
@ -44,7 +45,7 @@ ToAtom(JSContext *cx, const js::Value &v)
|
||||
return &str->asAtom();
|
||||
|
||||
JS::Anchor<JSString *> anchor(str);
|
||||
return AtomizeString(cx, str);
|
||||
return AtomizeString<allowGC>(cx, str);
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -94,8 +95,10 @@ BackfillIndexInCharBuffer(uint32_t index, mozilla::RangedPtr<T> end)
|
||||
return end;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
bool
|
||||
IndexToIdSlow(JSContext *cx, uint32_t index, MutableHandleId idp);
|
||||
IndexToIdSlow(JSContext *cx, uint32_t index,
|
||||
typename MaybeRooted<jsid, allowGC>::MutableHandleType idp);
|
||||
|
||||
inline bool
|
||||
IndexToId(JSContext *cx, uint32_t index, MutableHandleId idp)
|
||||
@ -107,7 +110,18 @@ IndexToId(JSContext *cx, uint32_t index, MutableHandleId idp)
|
||||
return true;
|
||||
}
|
||||
|
||||
return IndexToIdSlow(cx, index, idp);
|
||||
return IndexToIdSlow<CanGC>(cx, index, idp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
IndexToIdNoGC(JSContext *cx, uint32_t index, jsid *idp)
|
||||
{
|
||||
if (index <= JSID_INT_MAX) {
|
||||
*idp = INT_TO_JSID(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
return IndexToIdSlow<NoGC>(cx, index, idp);
|
||||
}
|
||||
|
||||
inline jsid
|
||||
@ -129,9 +143,9 @@ IdToString(JSContext *cx, jsid id)
|
||||
return JSID_TO_ATOM(id);
|
||||
|
||||
if (JS_LIKELY(JSID_IS_INT(id)))
|
||||
return Int32ToString(cx, JSID_TO_INT(id));
|
||||
return Int32ToString<CanGC>(cx, JSID_TO_INT(id));
|
||||
|
||||
JSString *str = ToStringSlow(cx, IdToValue(id));
|
||||
JSString *str = ToStringSlow<CanGC>(cx, IdToValue(id));
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
|
@ -840,7 +840,7 @@ JSStructuredCloneReader::readString(uint32_t nchars)
|
||||
Chars chars(context());
|
||||
if (!chars.allocate(nchars) || !in.readChars(chars.get(), nchars))
|
||||
return NULL;
|
||||
JSString *str = js_NewString(context(), chars.get(), nchars);
|
||||
JSString *str = js_NewString<CanGC>(context(), chars.get(), nchars);
|
||||
if (str)
|
||||
chars.forget();
|
||||
return str;
|
||||
@ -1111,7 +1111,7 @@ JSStructuredCloneReader::readId(jsid *idp)
|
||||
JSString *str = readString(data);
|
||||
if (!str)
|
||||
return false;
|
||||
JSAtom *atom = AtomizeString(context(), str);
|
||||
JSAtom *atom = AtomizeString<CanGC>(context(), str);
|
||||
if (!atom)
|
||||
return false;
|
||||
*idp = NON_INTEGER_ATOM_TO_JSID(atom);
|
||||
|
@ -2249,6 +2249,28 @@ class AutoObjectObjectHashMap : public AutoHashMapRooter<RawObject, RawObject>
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
class AutoAssertNoGCOrException : public AutoAssertNoGC
|
||||
{
|
||||
#ifdef DEBUG
|
||||
JSContext *cx;
|
||||
bool hadException;
|
||||
#endif
|
||||
|
||||
public:
|
||||
AutoAssertNoGCOrException(JSContext *cx)
|
||||
#ifdef DEBUG
|
||||
: cx(cx),
|
||||
hadException(cx->isExceptionPending())
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
~AutoAssertNoGCOrException()
|
||||
{
|
||||
JS_ASSERT_IF(!hadException, !cx->isExceptionPending());
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Allocation policy that uses JSRuntime::malloc_ and friends, so that
|
||||
* memory pressure is properly accounted for. This is suitable for
|
||||
|
@ -106,7 +106,7 @@ NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_)
|
||||
JS_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
|
||||
Entry *entry = &entries[entry_];
|
||||
|
||||
JSObject *obj = js_NewGCObject<DONT_ALLOW_GC>(cx, entry->kind);
|
||||
JSObject *obj = js_NewGCObject<NoGC>(cx, entry->kind);
|
||||
if (obj) {
|
||||
copyCachedToObject(obj, reinterpret_cast<JSObject *>(&entry->templateObject));
|
||||
Probes::createObject(cx, obj);
|
||||
|
@ -368,7 +368,7 @@ JSCompartment::wrap(JSContext *cx, Value *vp, JSObject *existingArg)
|
||||
Rooted<JSStableString *> str(cx, vp->toString()->ensureStable(cx));
|
||||
if (!str)
|
||||
return false;
|
||||
RootedString wrapped(cx, js_NewStringCopyN(cx, str->chars().get(), str->length()));
|
||||
RootedString wrapped(cx, js_NewStringCopyN<CanGC>(cx, str->chars().get(), str->length()));
|
||||
if (!wrapped)
|
||||
return false;
|
||||
vp->setString(wrapped);
|
||||
|
@ -1513,10 +1513,10 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
||||
}
|
||||
|
||||
template void *
|
||||
ArenaLists::refillFreeList<DONT_ALLOW_GC>(JSContext *cx, AllocKind thingKind);
|
||||
ArenaLists::refillFreeList<NoGC>(JSContext *cx, AllocKind thingKind);
|
||||
|
||||
template void *
|
||||
ArenaLists::refillFreeList<ALLOW_GC>(JSContext *cx, AllocKind thingKind);
|
||||
ArenaLists::refillFreeList<CanGC>(JSContext *cx, AllocKind thingKind);
|
||||
|
||||
JSGCTraceKind
|
||||
js_GetGCThingTraceKind(void *thing)
|
||||
@ -4782,6 +4782,6 @@ js_NewGCXML(JSContext *cx)
|
||||
if (!cx->runningWithTrustedPrincipals())
|
||||
++sE4XObjectsCreated;
|
||||
|
||||
return NewGCThing<JSXML, ALLOW_GC>(cx, js::gc::FINALIZE_XML, sizeof(JSXML));
|
||||
return NewGCThing<JSXML, CanGC>(cx, js::gc::FINALIZE_XML, sizeof(JSXML));
|
||||
}
|
||||
#endif
|
||||
|
@ -575,20 +575,20 @@ js_NewGCShortString(JSContext *cx)
|
||||
inline JSExternalString *
|
||||
js_NewGCExternalString(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<JSExternalString, js::ALLOW_GC>(cx, js::gc::FINALIZE_EXTERNAL_STRING,
|
||||
sizeof(JSExternalString));
|
||||
return js::gc::NewGCThing<JSExternalString, js::CanGC>(cx, js::gc::FINALIZE_EXTERNAL_STRING,
|
||||
sizeof(JSExternalString));
|
||||
}
|
||||
|
||||
inline JSScript *
|
||||
js_NewGCScript(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<JSScript, js::ALLOW_GC>(cx, js::gc::FINALIZE_SCRIPT, sizeof(JSScript));
|
||||
return js::gc::NewGCThing<JSScript, js::CanGC>(cx, js::gc::FINALIZE_SCRIPT, sizeof(JSScript));
|
||||
}
|
||||
|
||||
inline js::UnrootedShape
|
||||
js_NewGCShape(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<js::Shape, js::ALLOW_GC>(cx, js::gc::FINALIZE_SHAPE, sizeof(js::Shape));
|
||||
return js::gc::NewGCThing<js::Shape, js::CanGC>(cx, js::gc::FINALIZE_SHAPE, sizeof(js::Shape));
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
|
@ -2279,7 +2279,7 @@ TypeCompartment::newTypeObject(JSContext *cx, Class *clasp, Handle<TaggedProto>
|
||||
{
|
||||
JS_ASSERT_IF(proto.isObject(), cx->compartment == proto.toObject()->compartment());
|
||||
|
||||
TypeObject *object = gc::NewGCThing<TypeObject, ALLOW_GC>(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject));
|
||||
TypeObject *object = gc::NewGCThing<TypeObject, CanGC>(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject));
|
||||
if (!object)
|
||||
return NULL;
|
||||
new(object) TypeObject(clasp, proto, clasp == &FunctionClass, unknown);
|
||||
|
@ -608,7 +608,7 @@ TrackPropertyTypes(JSContext *cx, UnrootedObject obj, RawId id)
|
||||
|
||||
/* Add a possible type for a property of obj. */
|
||||
inline void
|
||||
AddTypePropertyId(JSContext *cx, HandleObject obj, RawId id, Type type)
|
||||
AddTypePropertyId(JSContext *cx, JSObject *obj, jsid id, Type type)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (cx->typeInferenceEnabled())
|
||||
@ -618,7 +618,7 @@ AddTypePropertyId(JSContext *cx, HandleObject obj, RawId id, Type type)
|
||||
}
|
||||
|
||||
inline void
|
||||
AddTypePropertyId(JSContext *cx, HandleObject obj, RawId id, const Value &value)
|
||||
AddTypePropertyId(JSContext *cx, JSObject *obj, jsid id, const Value &value)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (cx->typeInferenceEnabled())
|
||||
|
@ -938,27 +938,24 @@ inline InterpreterFrames::~InterpreterFrames()
|
||||
|
||||
#if defined(DEBUG) && !defined(JS_THREADSAFE) && !defined(JSGC_ROOT_ANALYSIS)
|
||||
void
|
||||
js::AssertValidPropertyCacheHit(JSContext *cx, JSObject *start_,
|
||||
js::AssertValidPropertyCacheHit(JSContext *cx, JSObject *start,
|
||||
JSObject *found, PropertyCacheEntry *entry)
|
||||
{
|
||||
jsbytecode *pc;
|
||||
JSScript *script = cx->stack.currentScript(&pc);
|
||||
|
||||
uint64_t sample = cx->runtime->gcNumber;
|
||||
PropertyCacheEntry savedEntry = *entry;
|
||||
|
||||
RootedPropertyName name(cx, GetNameFromBytecode(cx, script, pc, JSOp(*pc)));
|
||||
RootedObject start(cx, start_);
|
||||
RootedObject pobj(cx);
|
||||
RootedShape prop(cx);
|
||||
bool ok = baseops::LookupProperty(cx, start, name, &pobj, &prop);
|
||||
JS_ASSERT(ok);
|
||||
PropertyName *name = GetNameFromBytecode(cx, script, pc, JSOp(*pc));
|
||||
JSObject *pobj;
|
||||
Shape *prop;
|
||||
if (baseops::LookupProperty<NoGC>(cx, start, NameToId(name), &pobj, &prop)) {
|
||||
JS_ASSERT(prop);
|
||||
JS_ASSERT(pobj == found);
|
||||
JS_ASSERT(entry->prop == prop);
|
||||
}
|
||||
|
||||
if (cx->runtime->gcNumber != sample)
|
||||
cx->propertyCache().restore(&savedEntry);
|
||||
JS_ASSERT(prop);
|
||||
JS_ASSERT(pobj == found);
|
||||
JS_ASSERT(entry->prop == prop);
|
||||
JS_ASSERT(cx->runtime->gcNumber == sample);
|
||||
}
|
||||
#endif /* DEBUG && !JS_THREADSAFE */
|
||||
|
||||
@ -1910,9 +1907,9 @@ END_CASE(JSOP_CASE)
|
||||
BEGIN_CASE(JSOP_LT)
|
||||
{
|
||||
bool cond;
|
||||
const Value &lref = regs.sp[-2];
|
||||
const Value &rref = regs.sp[-1];
|
||||
if (!LessThanOperation(cx, lref, rref, &cond))
|
||||
MutableHandleValue lval = MutableHandleValue::fromMarkedLocation(®s.sp[-2]);
|
||||
MutableHandleValue rval = MutableHandleValue::fromMarkedLocation(®s.sp[-1]);
|
||||
if (!LessThanOperation(cx, lval, rval, &cond))
|
||||
goto error;
|
||||
TRY_BRANCH_AFTER_COND(cond, 2);
|
||||
regs.sp[-2].setBoolean(cond);
|
||||
@ -1923,9 +1920,9 @@ END_CASE(JSOP_LT)
|
||||
BEGIN_CASE(JSOP_LE)
|
||||
{
|
||||
bool cond;
|
||||
const Value &lref = regs.sp[-2];
|
||||
const Value &rref = regs.sp[-1];
|
||||
if (!LessThanOrEqualOperation(cx, lref, rref, &cond))
|
||||
MutableHandleValue lval = MutableHandleValue::fromMarkedLocation(®s.sp[-2]);
|
||||
MutableHandleValue rval = MutableHandleValue::fromMarkedLocation(®s.sp[-1]);
|
||||
if (!LessThanOrEqualOperation(cx, lval, rval, &cond))
|
||||
goto error;
|
||||
TRY_BRANCH_AFTER_COND(cond, 2);
|
||||
regs.sp[-2].setBoolean(cond);
|
||||
@ -1936,9 +1933,9 @@ END_CASE(JSOP_LE)
|
||||
BEGIN_CASE(JSOP_GT)
|
||||
{
|
||||
bool cond;
|
||||
const Value &lref = regs.sp[-2];
|
||||
const Value &rref = regs.sp[-1];
|
||||
if (!GreaterThanOperation(cx, lref, rref, &cond))
|
||||
MutableHandleValue lval = MutableHandleValue::fromMarkedLocation(®s.sp[-2]);
|
||||
MutableHandleValue rval = MutableHandleValue::fromMarkedLocation(®s.sp[-1]);
|
||||
if (!GreaterThanOperation(cx, lval, rval, &cond))
|
||||
goto error;
|
||||
TRY_BRANCH_AFTER_COND(cond, 2);
|
||||
regs.sp[-2].setBoolean(cond);
|
||||
@ -1949,9 +1946,9 @@ END_CASE(JSOP_GT)
|
||||
BEGIN_CASE(JSOP_GE)
|
||||
{
|
||||
bool cond;
|
||||
const Value &lref = regs.sp[-2];
|
||||
const Value &rref = regs.sp[-1];
|
||||
if (!GreaterThanOrEqualOperation(cx, lref, rref, &cond))
|
||||
MutableHandleValue lval = MutableHandleValue::fromMarkedLocation(®s.sp[-2]);
|
||||
MutableHandleValue rval = MutableHandleValue::fromMarkedLocation(®s.sp[-1]);
|
||||
if (!GreaterThanOrEqualOperation(cx, lval, rval, &cond))
|
||||
goto error;
|
||||
TRY_BRANCH_AFTER_COND(cond, 2);
|
||||
regs.sp[-2].setBoolean(cond);
|
||||
@ -3906,13 +3903,13 @@ template bool js::DeleteProperty<true> (JSContext *cx, HandleValue val, HandlePr
|
||||
template bool js::DeleteProperty<false>(JSContext *cx, HandleValue val, HandlePropertyName name, JSBool *bp);
|
||||
|
||||
bool
|
||||
js::GetElement(JSContext *cx, HandleValue lref, HandleValue rref, MutableHandleValue vp)
|
||||
js::GetElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue vp)
|
||||
{
|
||||
return GetElementOperation(cx, JSOP_GETELEM, lref, rref, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::GetElementMonitored(JSContext *cx, HandleValue lref, HandleValue rref,
|
||||
js::GetElementMonitored(JSContext *cx, MutableHandleValue lref, HandleValue rref,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
if (!GetElement(cx, lref, rref, vp))
|
||||
@ -3923,7 +3920,7 @@ js::GetElementMonitored(JSContext *cx, HandleValue lref, HandleValue rref,
|
||||
}
|
||||
|
||||
bool
|
||||
js::CallElement(JSContext *cx, HandleValue lref, HandleValue rref, MutableHandleValue res)
|
||||
js::CallElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res)
|
||||
{
|
||||
return GetElementOperation(cx, JSOP_CALLELEM, lref, rref, res);
|
||||
}
|
||||
|
@ -356,13 +356,13 @@ JSObject *
|
||||
Lambda(JSContext *cx, HandleFunction fun, HandleObject parent);
|
||||
|
||||
bool
|
||||
GetElement(JSContext *cx, HandleValue lref, HandleValue rref, MutableHandleValue res);
|
||||
GetElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res);
|
||||
|
||||
bool
|
||||
GetElementMonitored(JSContext *cx, HandleValue lref, HandleValue rref, MutableHandleValue res);
|
||||
GetElementMonitored(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res);
|
||||
|
||||
bool
|
||||
CallElement(JSContext *cx, HandleValue lref, HandleValue rref, MutableHandleValue res);
|
||||
CallElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res);
|
||||
|
||||
bool
|
||||
SetObjectElement(JSContext *cx, HandleObject obj, HandleValue index, HandleValue value,
|
||||
|
@ -181,14 +181,16 @@ ValuePropertyBearer(JSContext *cx, StackFrame *fp, HandleValue v, int spindex)
|
||||
}
|
||||
|
||||
inline bool
|
||||
NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, Shape *shapeArg,
|
||||
NativeGet(JSContext *cx, JSObject *objArg, JSObject *pobjArg, Shape *shapeArg,
|
||||
unsigned getHow, MutableHandleValue vp)
|
||||
{
|
||||
if (shapeArg->isDataDescriptor() && shapeArg->hasDefaultGetter()) {
|
||||
/* Fast path for Object instance properties. */
|
||||
JS_ASSERT(shapeArg->hasSlot());
|
||||
vp.set(pobj->nativeGetSlot(shapeArg->slot()));
|
||||
vp.set(pobjArg->nativeGetSlot(shapeArg->slot()));
|
||||
} else {
|
||||
RootedObject obj(cx, objArg);
|
||||
RootedObject pobj(cx, pobjArg);
|
||||
RootedShape shape(cx, shapeArg);
|
||||
if (!js_NativeGet(cx, obj, pobj, shape, getHow, vp))
|
||||
return false;
|
||||
@ -273,28 +275,27 @@ GetPropertyOperation(JSContext *cx, JSScript *script, jsbytecode *pc, MutableHan
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedObject obj(cx, ToObjectFromStack(cx, lval));
|
||||
JSObject *obj = ToObjectFromStack(cx, lval);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
PropertyCacheEntry *entry;
|
||||
Rooted<JSObject*> obj2(cx);
|
||||
JSObject *pobj;
|
||||
PropertyName *name;
|
||||
cx->propertyCache().test(cx, pc, obj.get(), obj2.get(), entry, name);
|
||||
cx->propertyCache().test(cx, pc, &obj, &pobj, &entry, &name);
|
||||
if (!name) {
|
||||
AssertValidPropertyCacheHit(cx, obj, obj2, entry);
|
||||
if (!NativeGet(cx, obj, obj2, entry->prop, JSGET_CACHE_RESULT, vp))
|
||||
return false;
|
||||
return true;
|
||||
AssertValidPropertyCacheHit(cx, obj, pobj, entry);
|
||||
return NativeGet(cx, obj, pobj, entry->prop, JSGET_CACHE_RESULT, vp);
|
||||
}
|
||||
|
||||
RootedId id(cx, NameToId(name));
|
||||
RootedObject nobj(cx, obj);
|
||||
|
||||
if (obj->getOps()->getProperty) {
|
||||
if (!GetPropertyGenericMaybeCallXML(cx, op, obj, id, vp))
|
||||
if (!GetPropertyGenericMaybeCallXML(cx, op, nobj, id, vp))
|
||||
return false;
|
||||
} else {
|
||||
if (!GetPropertyHelper(cx, obj, id, JSGET_CACHE_RESULT, vp))
|
||||
if (!GetPropertyHelper(cx, nobj, id, JSGET_CACHE_RESULT, vp))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -303,7 +304,7 @@ GetPropertyOperation(JSContext *cx, JSScript *script, jsbytecode *pc, MutableHan
|
||||
JS_UNLIKELY(vp.isPrimitive()) &&
|
||||
lval.isObject())
|
||||
{
|
||||
if (!OnUnknownMethod(cx, obj, IdToValue(id), vp))
|
||||
if (!OnUnknownMethod(cx, nobj, IdToValue(id), vp))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@ -410,7 +411,7 @@ FetchName(JSContext *cx, HandleObject obj, HandleObject obj2, HandlePropertyName
|
||||
}
|
||||
|
||||
inline bool
|
||||
FetchNameNoGC(JSContext *cx, JSObject *pobj, Shape *shape, MutableHandleValue vp)
|
||||
FetchNameNoGC(JSObject *pobj, Shape *shape, MutableHandleValue vp)
|
||||
{
|
||||
if (!shape || !pobj->isNative() || !shape->isDataDescriptor() || !shape->hasDefaultGetter())
|
||||
return false;
|
||||
@ -455,9 +456,8 @@ NameOperation(JSContext *cx, jsbytecode *pc, MutableHandleValue vp)
|
||||
Shape *shape = NULL;
|
||||
JSObject *scope = NULL, *pobj = NULL;
|
||||
if (LookupNameNoGC(cx, name, obj, &scope, &pobj, &shape)) {
|
||||
if (FetchNameNoGC(cx, pobj, shape, vp))
|
||||
if (FetchNameNoGC(pobj, shape, vp))
|
||||
return true;
|
||||
JS_ASSERT(!cx->isExceptionPending());
|
||||
}
|
||||
|
||||
RootedObject objRoot(cx, obj), scopeRoot(cx), pobjRoot(cx);
|
||||
@ -751,33 +751,48 @@ ToIdOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue ob
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
GetObjectElementOperation(JSContext *cx, JSOp op, HandleObject obj, const Value &rref, MutableHandleValue res)
|
||||
GetObjectElementOperation(JSContext *cx, JSOp op, JSObject *objArg, bool wasObject,
|
||||
HandleValue rref, MutableHandleValue res)
|
||||
{
|
||||
do {
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
if (op == JSOP_CALLELEM && JS_UNLIKELY(obj->isXML())) {
|
||||
RootedId id(cx);
|
||||
if (!FetchElementId(cx, obj, rref, &id, res))
|
||||
return false;
|
||||
return js_GetXMLMethod(cx, obj, id, res);
|
||||
}
|
||||
if (op == JSOP_CALLELEM && JS_UNLIKELY(objArg->isXML())) {
|
||||
RootedObject obj(cx, objArg);
|
||||
RootedId id(cx);
|
||||
if (!FetchElementId(cx, obj, rref, &id, res))
|
||||
return false;
|
||||
if (!js_GetXMLMethod(cx, obj, id, res))
|
||||
return false;
|
||||
objArg = obj;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
// Don't call GetPcScript (needed for analysis) from inside Ion since it's expensive.
|
||||
bool analyze = !cx->fp()->beginsIonActivation();
|
||||
|
||||
uint32_t index;
|
||||
if (IsDefinitelyIndex(rref, &index)) {
|
||||
if (analyze && !obj->isNative()) {
|
||||
JSScript *script = NULL;
|
||||
jsbytecode *pc = NULL;
|
||||
types::TypeScript::GetPcScript(cx, &script, &pc);
|
||||
// Don't call GetPcScript (needed for analysis) from inside Ion since it's expensive.
|
||||
bool analyze = !cx->fp()->beginsIonActivation();
|
||||
|
||||
if (script->hasAnalysis())
|
||||
script->analysis()->getCode(pc).nonNativeGetElement = true;
|
||||
uint32_t index;
|
||||
if (IsDefinitelyIndex(rref, &index)) {
|
||||
if (analyze && !objArg->isNative()) {
|
||||
JSScript *script = NULL;
|
||||
jsbytecode *pc = NULL;
|
||||
types::TypeScript::GetPcScript(cx, &script, &pc);
|
||||
|
||||
if (script->hasAnalysis())
|
||||
script->analysis()->getCode(pc).nonNativeGetElement = true;
|
||||
}
|
||||
|
||||
if (JSObject::getElementNoGC(cx, objArg, objArg, index, res.address()))
|
||||
break;
|
||||
|
||||
RootedObject obj(cx, objArg);
|
||||
if (!JSObject::getElement(cx, obj, obj, index, res))
|
||||
return false;
|
||||
objArg = obj;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!JSObject::getElement(cx, obj, obj, index, res))
|
||||
return false;
|
||||
} else {
|
||||
if (analyze) {
|
||||
JSScript *script = NULL;
|
||||
jsbytecode *pc = NULL;
|
||||
@ -786,37 +801,66 @@ GetObjectElementOperation(JSContext *cx, JSOp op, HandleObject obj, const Value
|
||||
if (script->hasAnalysis()) {
|
||||
script->analysis()->getCode(pc).getStringElement = true;
|
||||
|
||||
if (!obj->isArray() && !obj->isNative())
|
||||
if (!objArg->isArray() && !objArg->isNative())
|
||||
script->analysis()->getCode(pc).nonNativeGetElement = true;
|
||||
}
|
||||
}
|
||||
|
||||
Rooted<SpecialId> special(cx);
|
||||
res.set(rref);
|
||||
if (ValueIsSpecial(obj, res, &special, cx)) {
|
||||
if (!JSObject::getSpecial(cx, obj, obj, special, res))
|
||||
return false;
|
||||
} else {
|
||||
JSAtom *name = ToAtom(cx, res);
|
||||
if (!name)
|
||||
return false;
|
||||
if (ValueMightBeSpecial(rref)) {
|
||||
RootedObject obj(cx, objArg);
|
||||
Rooted<SpecialId> special(cx);
|
||||
res.set(rref);
|
||||
if (ValueIsSpecial(obj, res, &special, cx)) {
|
||||
if (!JSObject::getSpecial(cx, obj, obj, special, res))
|
||||
return false;
|
||||
objArg = obj;
|
||||
break;
|
||||
}
|
||||
objArg = obj;
|
||||
}
|
||||
|
||||
JSAtom *name = ToAtom<NoGC>(cx, rref);
|
||||
if (name) {
|
||||
if (name->isIndex(&index)) {
|
||||
if (!JSObject::getElement(cx, obj, obj, index, res))
|
||||
return false;
|
||||
if (JSObject::getElementNoGC(cx, objArg, objArg, index, res.address()))
|
||||
break;
|
||||
} else {
|
||||
if (!JSObject::getProperty(cx, obj, obj, name->asPropertyName(), res))
|
||||
return false;
|
||||
if (JSObject::getPropertyNoGC(cx, objArg, objArg, name->asPropertyName(), res.address()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RootedObject obj(cx, objArg);
|
||||
|
||||
name = ToAtom<CanGC>(cx, rref);
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
if (name->isIndex(&index)) {
|
||||
if (!JSObject::getElement(cx, obj, obj, index, res))
|
||||
return false;
|
||||
} else {
|
||||
if (!JSObject::getProperty(cx, obj, obj, name->asPropertyName(), res))
|
||||
return false;
|
||||
}
|
||||
|
||||
objArg = obj;
|
||||
} while (0);
|
||||
|
||||
#if JS_HAS_NO_SUCH_METHOD
|
||||
if (op == JSOP_CALLELEM && JS_UNLIKELY(res.isPrimitive()) && wasObject) {
|
||||
RootedObject obj(cx, objArg);
|
||||
if (!OnUnknownMethod(cx, obj, rref, res))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
assertSameCompartmentDebugOnly(cx, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
GetElementOperation(JSContext *cx, JSOp op, HandleValue lref, HandleValue rref,
|
||||
GetElementOperation(JSContext *cx, JSOp op, MutableHandleValue lref, HandleValue rref,
|
||||
MutableHandleValue res)
|
||||
{
|
||||
AssertCanGC();
|
||||
@ -835,8 +879,7 @@ GetElementOperation(JSContext *cx, JSOp op, HandleValue lref, HandleValue rref,
|
||||
}
|
||||
|
||||
StackFrame *fp = cx->fp();
|
||||
RootedValue lval(cx, lref);
|
||||
if (IsOptimizedArguments(fp, lval.address())) {
|
||||
if (IsOptimizedArguments(fp, lref.address())) {
|
||||
if (rref.isInt32()) {
|
||||
int32_t i = rref.toInt32();
|
||||
if (i >= 0 && uint32_t(i) < fp->numActualArgs()) {
|
||||
@ -849,23 +892,14 @@ GetElementOperation(JSContext *cx, JSOp op, HandleValue lref, HandleValue rref,
|
||||
if (!JSScript::argumentsOptimizationFailed(cx, script))
|
||||
return false;
|
||||
|
||||
lval = ObjectValue(fp->argsObj());
|
||||
lref.set(ObjectValue(fp->argsObj()));
|
||||
}
|
||||
|
||||
bool isObject = lval.isObject();
|
||||
RootedObject obj(cx, ToObjectFromStack(cx, lval));
|
||||
bool isObject = lref.isObject();
|
||||
JSObject *obj = ToObjectFromStack(cx, lref);
|
||||
if (!obj)
|
||||
return false;
|
||||
if (!GetObjectElementOperation(cx, op, obj, rref, res))
|
||||
return false;
|
||||
|
||||
#if JS_HAS_NO_SUCH_METHOD
|
||||
if (op == JSOP_CALLELEM && JS_UNLIKELY(res.isPrimitive()) && isObject) {
|
||||
if (!OnUnknownMethod(cx, obj, rref, res))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
return GetObjectElementOperation(cx, op, obj, isObject, rref, res);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
@ -946,26 +980,23 @@ InitArrayElemOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, uint32_t
|
||||
|
||||
#define RELATIONAL_OP(OP) \
|
||||
JS_BEGIN_MACRO \
|
||||
RootedValue lvalRoot(cx, lhs), rvalRoot(cx, rhs); \
|
||||
Value &lval = lvalRoot.get(); \
|
||||
Value &rval = rvalRoot.get(); \
|
||||
/* Optimize for two int-tagged operands (typical loop control). */ \
|
||||
if (lval.isInt32() && rval.isInt32()) { \
|
||||
*res = lval.toInt32() OP rval.toInt32(); \
|
||||
if (lhs.isInt32() && rhs.isInt32()) { \
|
||||
*res = lhs.toInt32() OP rhs.toInt32(); \
|
||||
} else { \
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, &lval)) \
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs.address())) \
|
||||
return false; \
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, &rval)) \
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs.address())) \
|
||||
return false; \
|
||||
if (lval.isString() && rval.isString()) { \
|
||||
JSString *l = lval.toString(), *r = rval.toString(); \
|
||||
if (lhs.isString() && rhs.isString()) { \
|
||||
JSString *l = lhs.toString(), *r = rhs.toString(); \
|
||||
int32_t result; \
|
||||
if (!CompareStrings(cx, l, r, &result)) \
|
||||
return false; \
|
||||
*res = result OP 0; \
|
||||
} else { \
|
||||
double l, r; \
|
||||
if (!ToNumber(cx, lval, &l) || !ToNumber(cx, rval, &r)) \
|
||||
if (!ToNumber(cx, lhs, &l) || !ToNumber(cx, rhs, &r)) \
|
||||
return false;; \
|
||||
*res = (l OP r); \
|
||||
} \
|
||||
@ -974,22 +1005,22 @@ InitArrayElemOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, uint32_t
|
||||
JS_END_MACRO
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
LessThanOperation(JSContext *cx, const Value &lhs, const Value &rhs, bool *res) {
|
||||
LessThanOperation(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) {
|
||||
RELATIONAL_OP(<);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
LessThanOrEqualOperation(JSContext *cx, const Value &lhs, const Value &rhs, bool *res) {
|
||||
LessThanOrEqualOperation(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) {
|
||||
RELATIONAL_OP(<=);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
GreaterThanOperation(JSContext *cx, const Value &lhs, const Value &rhs, bool *res) {
|
||||
GreaterThanOperation(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) {
|
||||
RELATIONAL_OP(>);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
GreaterThanOrEqualOperation(JSContext *cx, const Value &lhs, const Value &rhs, bool *res) {
|
||||
GreaterThanOrEqualOperation(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) {
|
||||
RELATIONAL_OP(>=);
|
||||
}
|
||||
|
||||
|
@ -515,6 +515,7 @@ ToCStringBuf::~ToCStringBuf()
|
||||
js_free(dbuf);
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
JSFlatString *
|
||||
js::Int32ToString(JSContext *cx, int32_t si)
|
||||
{
|
||||
@ -532,7 +533,7 @@ js::Int32ToString(JSContext *cx, int32_t si)
|
||||
if (JSFlatString *str = c->dtoaCache.lookup(10, si))
|
||||
return str;
|
||||
|
||||
JSShortString *str = js_NewGCShortString<ALLOW_GC>(cx);
|
||||
JSShortString *str = js_NewGCShortString<allowGC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
@ -551,6 +552,12 @@ js::Int32ToString(JSContext *cx, int32_t si)
|
||||
return str;
|
||||
}
|
||||
|
||||
template JSFlatString *
|
||||
js::Int32ToString<CanGC>(JSContext *cx, int32_t si);
|
||||
|
||||
template JSFlatString *
|
||||
js::Int32ToString<NoGC>(JSContext *cx, int32_t si);
|
||||
|
||||
/* Returns a non-NULL pointer to inside cbuf. */
|
||||
static char *
|
||||
IntToCString(ToCStringBuf *cbuf, int i, int base = 10)
|
||||
@ -587,6 +594,7 @@ IntToCString(ToCStringBuf *cbuf, int i, int base = 10)
|
||||
return cp.get();
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static JSString * JS_FASTCALL
|
||||
js_NumberToStringWithBase(JSContext *cx, double d, int base);
|
||||
|
||||
@ -610,7 +618,7 @@ num_toString_impl(JSContext *cx, CallArgs args)
|
||||
|
||||
base = int32_t(d2);
|
||||
}
|
||||
JSString *str = js_NumberToStringWithBase(cx, d, base);
|
||||
JSString *str = js_NumberToStringWithBase<CanGC>(cx, d, base);
|
||||
if (!str) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
@ -633,7 +641,7 @@ num_toLocaleString_impl(JSContext *cx, CallArgs args)
|
||||
|
||||
double d = Extract(args.thisv());
|
||||
|
||||
Rooted<JSString*> str(cx, js_NumberToStringWithBase(cx, d, 10));
|
||||
Rooted<JSString*> str(cx, js_NumberToStringWithBase<CanGC>(cx, d, 10));
|
||||
if (!str) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
@ -743,7 +751,7 @@ num_toLocaleString_impl(JSContext *cx, CallArgs args)
|
||||
return ok;
|
||||
}
|
||||
|
||||
str = js_NewStringCopyN(cx, buf, buflen);
|
||||
str = js_NewStringCopyN<CanGC>(cx, buf, buflen);
|
||||
js_free(buf);
|
||||
if (!str)
|
||||
return false;
|
||||
@ -803,7 +811,7 @@ DToStrResult(JSContext *cx, double d, JSDToStrMode mode, int precision, CallArgs
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
JSString *str = js_NewStringCopyZ(cx, numStr);
|
||||
JSString *str = js_NewStringCopyZ<CanGC>(cx, numStr);
|
||||
if (!str)
|
||||
return false;
|
||||
args.rval().setString(str);
|
||||
@ -871,7 +879,7 @@ num_toPrecision_impl(JSContext *cx, CallArgs args)
|
||||
double d = Extract(args.thisv());
|
||||
|
||||
if (!args.hasDefined(0)) {
|
||||
JSString *str = js_NumberToStringWithBase(cx, d, 10);
|
||||
JSString *str = js_NumberToStringWithBase<CanGC>(cx, d, 10);
|
||||
if (!str) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
@ -1210,6 +1218,7 @@ js::NumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base/* = 10
|
||||
: FracNumberToCString(cx, cbuf, d, base);
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static JSString * JS_FASTCALL
|
||||
js_NumberToStringWithBase(JSContext *cx, double d, int base)
|
||||
{
|
||||
@ -1258,21 +1267,28 @@ js_NumberToStringWithBase(JSContext *cx, double d, int base)
|
||||
cbuf.dbuf && cbuf.dbuf == numStr);
|
||||
}
|
||||
|
||||
JSFlatString *s = js_NewStringCopyZ(cx, numStr);
|
||||
JSFlatString *s = js_NewStringCopyZ<allowGC>(cx, numStr);
|
||||
c->dtoaCache.cache(base, d, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
JSString *
|
||||
js_NumberToString(JSContext *cx, double d)
|
||||
{
|
||||
return js_NumberToStringWithBase(cx, d, 10);
|
||||
return js_NumberToStringWithBase<allowGC>(cx, d, 10);
|
||||
}
|
||||
|
||||
template JSString *
|
||||
js_NumberToString<CanGC>(JSContext *cx, double d);
|
||||
|
||||
template JSString *
|
||||
js_NumberToString<NoGC>(JSContext *cx, double d);
|
||||
|
||||
JSFlatString *
|
||||
js::NumberToString(JSContext *cx, double d)
|
||||
{
|
||||
if (JSString *str = js_NumberToStringWithBase(cx, d, 10))
|
||||
if (JSString *str = js_NumberToStringWithBase<CanGC>(cx, d, 10))
|
||||
return &str->asFlat();
|
||||
return NULL;
|
||||
}
|
||||
@ -1287,7 +1303,7 @@ js::IndexToString(JSContext *cx, uint32_t index)
|
||||
if (JSFlatString *str = c->dtoaCache.lookup(10, index))
|
||||
return str;
|
||||
|
||||
JSShortString *str = js_NewGCShortString<ALLOW_GC>(cx);
|
||||
JSShortString *str = js_NewGCShortString<CanGC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
|
@ -47,11 +47,13 @@ class JSString;
|
||||
* ECMA-262-5 section 9.8.1; but note that it handles integers specially for
|
||||
* performance. See also js::NumberToCString().
|
||||
*/
|
||||
template <js::AllowGC allowGC>
|
||||
extern JSString *
|
||||
js_NumberToString(JSContext *cx, double d);
|
||||
|
||||
namespace js {
|
||||
|
||||
template <AllowGC allowGC>
|
||||
extern JSFlatString *
|
||||
Int32ToString(JSContext *cx, int32_t i);
|
||||
|
||||
|
146
js/src/jsobj.cpp
146
js/src/jsobj.cpp
@ -145,7 +145,7 @@ js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, Handl
|
||||
if (!lookup(cx, obj, id, objp, propp))
|
||||
return false;
|
||||
} else {
|
||||
if (!baseops::LookupProperty(cx, obj, id, objp, propp))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, obj, id, objp, propp))
|
||||
return false;
|
||||
}
|
||||
if (!propp)
|
||||
@ -1235,20 +1235,17 @@ js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp,
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto_, JSObject *parent_,
|
||||
js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *protoArg, JSObject *parentArg,
|
||||
gc::AllocKind kind)
|
||||
{
|
||||
if (proto_)
|
||||
return NewObjectWithGivenProto(cx, clasp, proto_, parent_, kind);
|
||||
|
||||
RootedObject parent(cx, parent_);
|
||||
RootedObject proto(cx, proto_);
|
||||
if (protoArg)
|
||||
return NewObjectWithGivenProto(cx, clasp, protoArg, parentArg, kind);
|
||||
|
||||
if (CanBeFinalizedInBackground(kind, clasp))
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
|
||||
if (!parent)
|
||||
parent = cx->global();
|
||||
if (!parentArg)
|
||||
parentArg = cx->global();
|
||||
|
||||
/*
|
||||
* Use the object cache, except for classes without a cached proto key.
|
||||
@ -1264,14 +1261,17 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto_, J
|
||||
NewObjectCache &cache = cx->runtime->newObjectCache;
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (parent->isGlobal() && protoKey != JSProto_Null) {
|
||||
if (cache.lookupGlobal(clasp, &parent->asGlobal(), kind, &entry)) {
|
||||
if (parentArg->isGlobal() && protoKey != JSProto_Null) {
|
||||
if (cache.lookupGlobal(clasp, &parentArg->asGlobal(), kind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry);
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
RootedObject parent(cx, parentArg);
|
||||
RootedObject proto(cx, protoArg);
|
||||
|
||||
if (!FindProto(cx, clasp, &proto))
|
||||
return NULL;
|
||||
|
||||
@ -1580,7 +1580,7 @@ JSObject::deleteByValue(JSContext *cx, HandleObject obj,
|
||||
if (ValueIsSpecial(obj, &propval, &sid, cx))
|
||||
return deleteSpecial(cx, obj, sid, rval, strict);
|
||||
|
||||
JSAtom *name = ToAtom(cx, propval);
|
||||
JSAtom *name = ToAtom<CanGC>(cx, propval);
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
@ -3068,7 +3068,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal
|
||||
* property cache line for (obj, id) to map shape.
|
||||
*/
|
||||
RootedObject pobj(cx);
|
||||
if (!baseops::LookupProperty(cx, obj, id, &pobj, &shape))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, obj, id, &pobj, &shape))
|
||||
return false;
|
||||
if (shape && pobj == obj) {
|
||||
if (IsImplicitDenseElement(shape)) {
|
||||
@ -3244,7 +3244,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
||||
}
|
||||
|
||||
if (JSID_IS_INT(id) && objp->containsDenseElement(JSID_TO_INT(id))) {
|
||||
MarkDenseElementFound<ALLOW_GC>(propp);
|
||||
MarkDenseElementFound<CanGC>(propp);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3338,14 +3338,27 @@ LookupPropertyWithFlagsInline(JSContext *cx,
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
baseops::LookupProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp,
|
||||
MutableHandleShape propp)
|
||||
template <AllowGC allowGC>
|
||||
JSBool
|
||||
baseops::LookupProperty(JSContext *cx,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<jsid, allowGC>::HandleType id,
|
||||
typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
|
||||
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
|
||||
{
|
||||
return LookupPropertyWithFlagsInline<ALLOW_GC>(cx, obj, id, cx->resolveFlags, objp, propp);
|
||||
return LookupPropertyWithFlagsInline<allowGC>(cx, obj, id, cx->resolveFlags, objp, propp);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
template JSBool
|
||||
baseops::LookupProperty<CanGC>(JSContext *cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
|
||||
template JSBool
|
||||
baseops::LookupProperty<NoGC>(JSContext *cx, JSObject *obj, jsid id,
|
||||
FakeMutableHandle<JSObject*> objp,
|
||||
FakeMutableHandle<Shape*> propp);
|
||||
|
||||
JSBool
|
||||
baseops::LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
{
|
||||
@ -3353,14 +3366,14 @@ baseops::LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
|
||||
return LookupPropertyWithFlagsInline<ALLOW_GC>(cx, obj, id, cx->resolveFlags, objp, propp);
|
||||
return LookupPropertyWithFlagsInline<CanGC>(cx, obj, id, cx->resolveFlags, objp, propp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
{
|
||||
return LookupPropertyWithFlagsInline<ALLOW_GC>(cx, obj, id, flags, objp, propp);
|
||||
return LookupPropertyWithFlagsInline<CanGC>(cx, obj, id, flags, objp, propp);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -3388,17 +3401,16 @@ bool
|
||||
js::LookupNameNoGC(JSContext *cx, PropertyName *name, JSObject *scopeChain,
|
||||
JSObject **objp, JSObject **pobjp, Shape **propp)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
AutoAssertNoGCOrException nogc(cx);
|
||||
|
||||
JS_ASSERT(!*objp && !*pobjp && !*propp);
|
||||
|
||||
for (JSObject *scope = scopeChain; scope; scope = scope->enclosingScope()) {
|
||||
if (scope->getOps()->lookupGeneric)
|
||||
return false;
|
||||
if (!LookupPropertyWithFlagsInline<DONT_ALLOW_GC>(cx, scope, NameToId(name),
|
||||
cx->resolveFlags, pobjp, propp))
|
||||
if (!LookupPropertyWithFlagsInline<NoGC>(cx, scope, NameToId(name),
|
||||
cx->resolveFlags, pobjp, propp))
|
||||
{
|
||||
JS_ASSERT(!cx->isExceptionPending());
|
||||
return false;
|
||||
}
|
||||
if (*propp) {
|
||||
@ -3431,10 +3443,15 @@ js::LookupNameWithGlobalDefault(JSContext *cx, HandlePropertyName name, HandleOb
|
||||
return true;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
js_NativeGetInline(JSContext *cx, Handle<JSObject*> receiver, Handle<JSObject*> obj,
|
||||
Handle<JSObject*> pobj, Handle<Shape*> shape, unsigned getHow,
|
||||
MutableHandle<Value> vp)
|
||||
NativeGetInline(JSContext *cx,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType receiver,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType pobj,
|
||||
typename MaybeRooted<Shape*, allowGC>::HandleType shape,
|
||||
unsigned getHow,
|
||||
typename MaybeRooted<Value, allowGC>::MutableHandleType vp)
|
||||
{
|
||||
JS_ASSERT(pobj->isNative());
|
||||
|
||||
@ -3459,9 +3476,18 @@ js_NativeGetInline(JSContext *cx, Handle<JSObject*> receiver, Handle<JSObject*>
|
||||
}
|
||||
}
|
||||
|
||||
if (!shape->get(cx, receiver, obj, pobj, vp))
|
||||
if (!allowGC)
|
||||
return false;
|
||||
|
||||
if (!shape->get(cx,
|
||||
MaybeRooted<JSObject*, allowGC>::toHandle(receiver),
|
||||
MaybeRooted<JSObject*, allowGC>::toHandle(obj),
|
||||
MaybeRooted<JSObject*, allowGC>::toHandle(pobj),
|
||||
MaybeRooted<Value, allowGC>::toMutableHandle(vp)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Update slotful shapes according to the value produced by the getter. */
|
||||
if (shape->hasSlot() && pobj->nativeContains(cx, shape))
|
||||
pobj->nativeSetSlot(shape->slot(), vp);
|
||||
@ -3473,7 +3499,7 @@ JSBool
|
||||
js_NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, Handle<Shape*> shape,
|
||||
unsigned getHow, MutableHandle<Value> vp)
|
||||
{
|
||||
return js_NativeGetInline(cx, obj, obj, pobj, shape, getHow, vp);
|
||||
return NativeGetInline<CanGC>(cx, obj, obj, pobj, shape, getHow, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -3523,21 +3549,34 @@ js_NativeSet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> receiver,
|
||||
return true;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
uint32_t getHow, MutableHandleValue vp)
|
||||
GetPropertyHelperInline(JSContext *cx,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType receiver,
|
||||
typename MaybeRooted<jsid, allowGC>::HandleType id,
|
||||
uint32_t getHow,
|
||||
typename MaybeRooted<Value, allowGC>::MutableHandleType vp)
|
||||
{
|
||||
/* This call site is hot -- use the always-inlined variant of LookupPropertyWithFlags(). */
|
||||
RootedObject obj2(cx);
|
||||
RootedShape shape(cx);
|
||||
if (!LookupPropertyWithFlagsInline<ALLOW_GC>(cx, obj, id, cx->resolveFlags, &obj2, &shape))
|
||||
typename MaybeRooted<JSObject*, allowGC>::RootType obj2(cx);
|
||||
typename MaybeRooted<Shape*, allowGC>::RootType shape(cx);
|
||||
if (!LookupPropertyWithFlagsInline<allowGC>(cx, obj, id, cx->resolveFlags, &obj2, &shape))
|
||||
return false;
|
||||
|
||||
if (!shape) {
|
||||
if (!allowGC)
|
||||
return false;
|
||||
|
||||
vp.setUndefined();
|
||||
|
||||
if (!CallJSPropertyOp(cx, obj->getClass()->getProperty, obj, id, vp))
|
||||
return JS_FALSE;
|
||||
if (!CallJSPropertyOp(cx, obj->getClass()->getProperty,
|
||||
MaybeRooted<JSObject*, allowGC>::toHandle(obj),
|
||||
MaybeRooted<jsid, allowGC>::toHandle(id),
|
||||
MaybeRooted<Value, allowGC>::toMutableHandle(vp)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Record non-undefined values produced by the class getter hook. */
|
||||
if (!vp.isUndefined())
|
||||
@ -3598,9 +3637,15 @@ js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receive
|
||||
}
|
||||
|
||||
if (!obj2->isNative()) {
|
||||
if (!allowGC)
|
||||
return false;
|
||||
HandleObject obj2Handle = MaybeRooted<JSObject*, allowGC>::toHandle(obj2);
|
||||
HandleObject receiverHandle = MaybeRooted<JSObject*, allowGC>::toHandle(receiver);
|
||||
HandleId idHandle = MaybeRooted<jsid, allowGC>::toHandle(id);
|
||||
MutableHandleValue vpHandle = MaybeRooted<Value, allowGC>::toMutableHandle(vp);
|
||||
return obj2->isProxy()
|
||||
? Proxy::get(cx, obj2, receiver, id, vp)
|
||||
: JSObject::getGeneric(cx, obj2, obj2, id, vp);
|
||||
? Proxy::get(cx, obj2Handle, receiverHandle, idHandle, vpHandle)
|
||||
: JSObject::getGeneric(cx, obj2Handle, obj2Handle, idHandle, vpHandle);
|
||||
}
|
||||
|
||||
if (IsImplicitDenseElement(shape)) {
|
||||
@ -3612,7 +3657,7 @@ js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receive
|
||||
cx->propertyCache().fill(cx, obj, obj2, shape);
|
||||
|
||||
/* This call site is hot -- use the always-inlined variant of js_NativeGet(). */
|
||||
if (!js_NativeGetInline(cx, receiver, obj, obj2, shape, getHow, vp))
|
||||
if (!NativeGetInline<allowGC>(cx, obj, receiver, obj2, shape, getHow, vp))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
@ -3621,14 +3666,21 @@ js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receive
|
||||
bool
|
||||
js::GetPropertyHelper(JSContext *cx, HandleObject obj, HandleId id, uint32_t getHow, MutableHandleValue vp)
|
||||
{
|
||||
return !!js_GetPropertyHelperInline(cx, obj, obj, id, getHow, vp);
|
||||
return GetPropertyHelperInline<CanGC>(cx, obj, obj, id, getHow, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
baseops::GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
/* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */
|
||||
return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp);
|
||||
/* This call site is hot -- use the always-inlined variant of GetPropertyHelper(). */
|
||||
return GetPropertyHelperInline<CanGC>(cx, obj, receiver, id, 0, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
baseops::GetPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
|
||||
{
|
||||
AutoAssertNoGCOrException nogc(cx);
|
||||
return GetPropertyHelperInline<NoGC>(cx, obj, receiver, id, 0, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -3640,7 +3692,7 @@ baseops::GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint
|
||||
return false;
|
||||
|
||||
/* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */
|
||||
return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp);
|
||||
return GetPropertyHelperInline<CanGC>(cx, obj, receiver, id, 0, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -4020,7 +4072,7 @@ baseops::GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a
|
||||
{
|
||||
RootedObject nobj(cx);
|
||||
RootedShape shape(cx);
|
||||
if (!baseops::LookupProperty(cx, obj, id, &nobj, &shape))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, obj, id, &nobj, &shape))
|
||||
return false;
|
||||
if (!shape) {
|
||||
*attrsp = 0;
|
||||
@ -4056,7 +4108,7 @@ baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a
|
||||
{
|
||||
RootedObject nobj(cx);
|
||||
RootedShape shape(cx);
|
||||
if (!baseops::LookupProperty(cx, obj, id, &nobj, &shape))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, obj, id, &nobj, &shape))
|
||||
return false;
|
||||
if (!shape)
|
||||
return true;
|
||||
@ -4097,7 +4149,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHand
|
||||
|
||||
RootedObject proto(cx);
|
||||
RootedShape shape(cx);
|
||||
if (!baseops::LookupProperty(cx, obj, id, &proto, &shape))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, obj, id, &proto, &shape))
|
||||
return false;
|
||||
if (!shape || proto != obj) {
|
||||
/*
|
||||
|
@ -101,19 +101,23 @@ namespace baseops {
|
||||
* property of *objp stored in *propp. If successful but id was not found,
|
||||
* return true with both *objp and *propp null.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
LookupProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp,
|
||||
MutableHandleShape propp);
|
||||
template <AllowGC allowGC>
|
||||
extern JSBool
|
||||
LookupProperty(JSContext *cx,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<jsid, allowGC>::HandleType id,
|
||||
typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
|
||||
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp);
|
||||
|
||||
inline bool
|
||||
LookupProperty(JSContext *cx, HandleObject obj, PropertyName *name,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
{
|
||||
Rooted<jsid> id(cx, NameToId(name));
|
||||
return LookupProperty(cx, obj, id, objp, propp);
|
||||
return LookupProperty<CanGC>(cx, obj, id, objp, propp);
|
||||
}
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
extern JSBool
|
||||
LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
|
||||
@ -136,6 +140,9 @@ DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value
|
||||
extern JSBool
|
||||
GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, MutableHandleValue vp);
|
||||
|
||||
extern JSBool
|
||||
GetPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
|
||||
|
||||
extern JSBool
|
||||
GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, MutableHandleValue vp);
|
||||
|
||||
@ -860,12 +867,18 @@ class JSObject : public js::ObjectImpl
|
||||
static inline JSBool getGeneric(JSContext *cx, js::HandleObject obj,
|
||||
js::HandleObject receiver,
|
||||
js::HandleId id, js::MutableHandleValue vp);
|
||||
static inline JSBool getGenericNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||
jsid id, js::Value *vp);
|
||||
static inline JSBool getProperty(JSContext *cx, js::HandleObject obj,
|
||||
js::HandleObject receiver,
|
||||
js::PropertyName *name, js::MutableHandleValue vp);
|
||||
static inline JSBool getPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||
js::PropertyName *name, js::Value *vp);
|
||||
static inline JSBool getElement(JSContext *cx, js::HandleObject obj,
|
||||
js::HandleObject receiver,
|
||||
uint32_t index, js::MutableHandleValue vp);
|
||||
static inline JSBool getElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||
uint32_t index, js::Value *vp);
|
||||
/* If element is not present (e.g. array hole) *present is set to
|
||||
false and the contents of *vp are unusable garbage. */
|
||||
static inline JSBool getElementIfPresent(JSContext *cx, js::HandleObject obj,
|
||||
|
@ -177,6 +177,16 @@ JSObject::getGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject recei
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ inline JSBool
|
||||
JSObject::getGenericNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||
jsid id, js::Value *vp)
|
||||
{
|
||||
js::GenericIdOp op = obj->getOps()->getGeneric;
|
||||
if (op)
|
||||
return false;
|
||||
return js::baseops::GetPropertyNoGC(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
/* static */ inline JSBool
|
||||
JSObject::getProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
|
||||
js::PropertyName *name, js::MutableHandleValue vp)
|
||||
@ -185,6 +195,13 @@ JSObject::getProperty(JSContext *cx, js::HandleObject obj, js::HandleObject rece
|
||||
return getGeneric(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
/* static */ inline JSBool
|
||||
JSObject::getPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||
js::PropertyName *name, js::Value *vp)
|
||||
{
|
||||
return getGenericNoGC(cx, obj, receiver, js::NameToId(name), vp);
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
JSObject::deleteProperty(JSContext *cx, js::HandleObject obj,
|
||||
js::HandlePropertyName name, js::MutableHandleValue rval, bool strict)
|
||||
@ -969,7 +986,7 @@ JSObject::create(JSContext *cx, js::gc::AllocKind kind,
|
||||
JS_ASSERT(js::gc::GetGCKindSlots(kind, type->clasp) == shape->numFixedSlots());
|
||||
JS_ASSERT(cx->compartment == type->compartment());
|
||||
|
||||
JSObject *obj = js_NewGCObject<js::ALLOW_GC>(cx, kind);
|
||||
JSObject *obj = js_NewGCObject<js::CanGC>(cx, kind);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
@ -1014,7 +1031,7 @@ JSObject::createArray(JSContext *cx, js::gc::AllocKind kind,
|
||||
|
||||
uint32_t capacity = js::gc::GetGCKindSlots(kind) - js::ObjectElements::VALUES_PER_HEADER;
|
||||
|
||||
JSObject *obj = js_NewGCObject<js::ALLOW_GC>(cx, kind);
|
||||
JSObject *obj = js_NewGCObject<js::CanGC>(cx, kind);
|
||||
if (!obj) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
@ -1140,7 +1157,7 @@ JSObject::lookupGeneric(JSContext *cx, js::HandleObject obj, js::HandleId id,
|
||||
js::LookupGenericOp op = obj->getOps()->lookupGeneric;
|
||||
if (op)
|
||||
return op(cx, obj, id, objp, propp);
|
||||
return js::baseops::LookupProperty(cx, obj, id, objp, propp);
|
||||
return js::baseops::LookupProperty<js::CanGC>(cx, obj, id, objp, propp);
|
||||
}
|
||||
|
||||
/* static */ inline JSBool
|
||||
@ -1225,6 +1242,20 @@ JSObject::getElement(JSContext *cx, js::HandleObject obj, js::HandleObject recei
|
||||
return getGeneric(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
/* static */ inline JSBool
|
||||
JSObject::getElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||
uint32_t index, js::Value *vp)
|
||||
{
|
||||
js::ElementIdOp op = obj->getOps()->getElement;
|
||||
if (op)
|
||||
return false;
|
||||
|
||||
jsid id;
|
||||
if (!js::IndexToIdNoGC(cx, index, &id))
|
||||
return false;
|
||||
return getGenericNoGC(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
/* static */ inline JSBool
|
||||
JSObject::getElementIfPresent(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
|
||||
uint32_t index, js::MutableHandleValue vp,
|
||||
@ -1739,6 +1770,12 @@ IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx)
|
||||
return ObjectClassIs(v.toObject(), classValue, cx);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
ValueMightBeSpecial(const Value &propval)
|
||||
{
|
||||
return propval.isObject();
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
ValueIsSpecial(JSObject *obj, MutableHandleValue propval, MutableHandle<SpecialId> sidp,
|
||||
JSContext *cx)
|
||||
|
@ -335,7 +335,7 @@ PreprocessValue(JSContext *cx, HandleObject holder, KeyType key, MutableHandleVa
|
||||
return false;
|
||||
vp.set(NumberValue(d));
|
||||
} else if (ObjectClassIs(obj, ESClass_String, cx)) {
|
||||
JSString *str = ToStringSlow(cx, vp);
|
||||
JSString *str = ToStringSlow<CanGC>(cx, vp);
|
||||
if (!str)
|
||||
return false;
|
||||
vp.set(StringValue(str));
|
||||
@ -689,7 +689,7 @@ js_Stringify(JSContext *cx, MutableHandleValue vp, JSObject *replacer_, Value sp
|
||||
return false;
|
||||
space = NumberValue(d);
|
||||
} else if (ObjectClassIs(*spaceObj, ESClass_String, cx)) {
|
||||
JSString *str = ToStringSlow(cx, space);
|
||||
JSString *str = ToStringSlow<CanGC>(cx, space);
|
||||
if (!str)
|
||||
return false;
|
||||
space = StringValue(str);
|
||||
|
@ -57,8 +57,8 @@ JSONParser::readString()
|
||||
size_t length = current - start;
|
||||
current++;
|
||||
JSFlatString *str = (ST == JSONParser::PropertyName)
|
||||
? AtomizeChars(cx, start.get(), length)
|
||||
: js_NewStringCopyN(cx, start.get(), length);
|
||||
? AtomizeChars<CanGC>(cx, start.get(), length)
|
||||
: js_NewStringCopyN<CanGC>(cx, start.get(), length);
|
||||
if (!str)
|
||||
return token(OOM);
|
||||
return stringToken(str);
|
||||
|
@ -155,8 +155,8 @@ class PropertyCache
|
||||
|
||||
public:
|
||||
JS_ALWAYS_INLINE void test(JSContext *cx, jsbytecode *pc,
|
||||
JSObject *&obj, JSObject *&pobj,
|
||||
PropertyCacheEntry *&entry, PropertyName *&name);
|
||||
JSObject **obj, JSObject **pobj,
|
||||
PropertyCacheEntry **entry, PropertyName **name);
|
||||
|
||||
/*
|
||||
* Test for cached information about a property set on *objp at pc.
|
||||
|
@ -28,35 +28,35 @@
|
||||
* caches (on all threads) by re-generating JSObject::shape().
|
||||
*/
|
||||
JS_ALWAYS_INLINE void
|
||||
js::PropertyCache::test(JSContext *cx, jsbytecode *pc, JSObject *&obj,
|
||||
JSObject *&pobj, PropertyCacheEntry *&entry, PropertyName *&name)
|
||||
js::PropertyCache::test(JSContext *cx, jsbytecode *pc, JSObject **obj,
|
||||
JSObject **pobj, PropertyCacheEntry **entry, PropertyName **name)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
|
||||
JS_ASSERT(this == &cx->propertyCache());
|
||||
|
||||
UnrootedShape kshape = obj->lastProperty();
|
||||
entry = &table[hash(pc, kshape)];
|
||||
PCMETER(pctestentry = entry);
|
||||
UnrootedShape kshape = (*obj)->lastProperty();
|
||||
*entry = &table[hash(pc, kshape)];
|
||||
PCMETER(pctestentry = *entry);
|
||||
PCMETER(tests++);
|
||||
JS_ASSERT(&obj != &pobj);
|
||||
if (entry->kpc == pc && entry->kshape == kshape) {
|
||||
JS_ASSERT(obj != pobj);
|
||||
if ((*entry)->kpc == pc && (*entry)->kshape == kshape) {
|
||||
JSObject *tmp;
|
||||
pobj = obj;
|
||||
if (entry->isPrototypePropertyHit() &&
|
||||
(tmp = pobj->getProto()) != NULL) {
|
||||
pobj = tmp;
|
||||
*pobj = *obj;
|
||||
if ((*entry)->isPrototypePropertyHit() &&
|
||||
(tmp = (*pobj)->getProto()) != NULL) {
|
||||
*pobj = tmp;
|
||||
}
|
||||
|
||||
if (pobj->lastProperty() == entry->pshape) {
|
||||
if ((*pobj)->lastProperty() == (*entry)->pshape) {
|
||||
PCMETER(pchits++);
|
||||
PCMETER(entry->isOwnPropertyHit() || protopchits++);
|
||||
name = NULL;
|
||||
PCMETER((*entry)->isOwnPropertyHit() || protopchits++);
|
||||
*name = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
name = fullTest(cx, pc, &obj, &pobj, entry);
|
||||
if (name)
|
||||
*name = fullTest(cx, pc, obj, pobj, *entry);
|
||||
if (!*name)
|
||||
PCMETER(misses++);
|
||||
}
|
||||
|
||||
|
@ -265,7 +265,7 @@ Shape::dump(JSContext *cx, FILE *fp) const
|
||||
str = JSID_TO_ATOM(propid);
|
||||
} else {
|
||||
JS_ASSERT(JSID_IS_OBJECT(propid));
|
||||
JSString *s = ToStringSlow(cx, IdToValue(propid));
|
||||
JSString *s = ToStringSlow<CanGC>(cx, IdToValue(propid));
|
||||
fputs("object ", fp);
|
||||
str = s ? s->ensureLinear(cx) : NULL;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ Shape::makeOwnBaseShape(JSContext *cx)
|
||||
JS_ASSERT(!base()->isOwned());
|
||||
assertSameCompartmentDebugOnly(cx, compartment());
|
||||
|
||||
UnrootedBaseShape nbase = js_NewGCBaseShape<DONT_ALLOW_GC>(cx);
|
||||
UnrootedBaseShape nbase = js_NewGCBaseShape<NoGC>(cx);
|
||||
if (!nbase)
|
||||
return false;
|
||||
|
||||
@ -1140,7 +1140,7 @@ BaseShape::getUnowned(JSContext *cx, const StackBaseShape &base)
|
||||
|
||||
StackBaseShape::AutoRooter root(cx, &base);
|
||||
|
||||
UnrootedBaseShape nbase_ = js_NewGCBaseShape<ALLOW_GC>(cx);
|
||||
UnrootedBaseShape nbase_ = js_NewGCBaseShape<CanGC>(cx);
|
||||
if (!nbase_)
|
||||
return NULL;
|
||||
|
||||
|
@ -515,9 +515,9 @@ MarkDenseElementFound(typename MaybeRooted<Shape*, allowGC>::MutableHandleType p
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsImplicitDenseElement(HandleShape prop)
|
||||
IsImplicitDenseElement(Shape *prop)
|
||||
{
|
||||
return prop.get() == reinterpret_cast<Shape*>(1);
|
||||
return prop == reinterpret_cast<Shape*>(1);
|
||||
}
|
||||
|
||||
static inline uint8_t
|
||||
|
@ -1214,7 +1214,7 @@ ScriptSource::substring(JSContext *cx, uint32_t start, uint32_t stop)
|
||||
return NULL;
|
||||
}
|
||||
decompressed[length_] = 0;
|
||||
cached = js_NewString(cx, decompressed, length_);
|
||||
cached = js_NewString<CanGC>(cx, decompressed, length_);
|
||||
if (!cached) {
|
||||
js_free(decompressed);
|
||||
return NULL;
|
||||
@ -1229,7 +1229,7 @@ ScriptSource::substring(JSContext *cx, uint32_t start, uint32_t stop)
|
||||
#else
|
||||
chars = data.source;
|
||||
#endif
|
||||
return js_NewStringCopyN(cx, chars + start, stop - start);
|
||||
return js_NewStringCopyN<CanGC>(cx, chars + start, stop - start);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -194,7 +194,7 @@ str_escape(JSContext *cx, unsigned argc, Value *vp)
|
||||
JS_ASSERT(ni == newlength);
|
||||
newchars[newlength] = 0;
|
||||
|
||||
JSString *retstr = js_NewString(cx, newchars, newlength);
|
||||
JSString *retstr = js_NewString<CanGC>(cx, newchars, newlength);
|
||||
if (!retstr) {
|
||||
js_free(newchars);
|
||||
return false;
|
||||
@ -456,7 +456,7 @@ ThisToStringForStringProto(JSContext *cx, CallReceiver call)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSString *str = ToStringSlow(cx, call.thisv());
|
||||
JSString *str = ToStringSlow<CanGC>(cx, call.thisv());
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
@ -626,7 +626,7 @@ js_toLowerCase(JSContext *cx, JSString *str)
|
||||
for (size_t i = 0; i < n; i++)
|
||||
news[i] = unicode::ToLowerCase(s[i]);
|
||||
news[n] = 0;
|
||||
str = js_NewString(cx, news, n);
|
||||
str = js_NewString<CanGC>(cx, news, n);
|
||||
if (!str) {
|
||||
js_free(news);
|
||||
return NULL;
|
||||
@ -693,7 +693,7 @@ js_toUpperCase(JSContext *cx, JSString *str)
|
||||
for (size_t i = 0; i < n; i++)
|
||||
news[i] = unicode::ToUpperCase(s[i]);
|
||||
news[n] = 0;
|
||||
str = js_NewString(cx, news, n);
|
||||
str = js_NewString<CanGC>(cx, news, n);
|
||||
if (!str) {
|
||||
js_free(news);
|
||||
return NULL;
|
||||
@ -1600,7 +1600,7 @@ class StringRegExpGuard
|
||||
if (!arg)
|
||||
return false;
|
||||
|
||||
fm.patstr = AtomizeString(cx, arg);
|
||||
fm.patstr = AtomizeString<CanGC>(cx, arg);
|
||||
if (!fm.patstr)
|
||||
return false;
|
||||
}
|
||||
@ -2010,7 +2010,7 @@ FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t
|
||||
if (str->isAtom()) {
|
||||
atom = &str->asAtom();
|
||||
} else {
|
||||
atom = AtomizeString(cx, str);
|
||||
atom = AtomizeString<CanGC>(cx, str);
|
||||
if (!atom)
|
||||
return false;
|
||||
}
|
||||
@ -2804,7 +2804,7 @@ SplitHelper(JSContext *cx, Handle<JSStableString*> str, uint32_t limit, const Ma
|
||||
if (!matches[i + 1].isUndefined()) {
|
||||
JSSubString parsub;
|
||||
res->getParen(i + 1, &parsub);
|
||||
sub = js_NewStringCopyN(cx, parsub.chars, parsub.length);
|
||||
sub = js_NewStringCopyN<CanGC>(cx, parsub.chars, parsub.length);
|
||||
if (!sub || !splits.append(StringValue(sub)))
|
||||
return NULL;
|
||||
} else {
|
||||
@ -3408,7 +3408,7 @@ js::str_fromCharCode(JSContext *cx, unsigned argc, Value *vp)
|
||||
chars[i] = (jschar)code;
|
||||
}
|
||||
chars[args.length()] = 0;
|
||||
JSString *str = js_NewString(cx, chars, args.length());
|
||||
JSString *str = js_NewString<CanGC>(cx, chars, args.length());
|
||||
if (!str) {
|
||||
js_free(chars);
|
||||
return JS_FALSE;
|
||||
@ -3472,15 +3472,22 @@ js_InitStringClass(JSContext *cx, HandleObject obj)
|
||||
return proto;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
JSStableString *
|
||||
js_NewString(JSContext *cx, jschar *chars, size_t length)
|
||||
{
|
||||
JSStableString *s = JSStableString::new_(cx, chars, length);
|
||||
JSStableString *s = JSStableString::new_<allowGC>(cx, chars, length);
|
||||
if (s)
|
||||
Probes::createString(cx, s, length);
|
||||
return s;
|
||||
}
|
||||
|
||||
template JSStableString *
|
||||
js_NewString<CanGC>(JSContext *cx, jschar *chars, size_t length);
|
||||
|
||||
template JSStableString *
|
||||
js_NewString<NoGC>(JSContext *cx, jschar *chars, size_t length);
|
||||
|
||||
JSLinearString *
|
||||
js_NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t length)
|
||||
{
|
||||
@ -3504,62 +3511,90 @@ js_NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t len
|
||||
return s;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
JSFlatString *
|
||||
js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n)
|
||||
{
|
||||
if (JSShortString::lengthFits(n))
|
||||
return NewShortString(cx, TwoByteChars(s, n));
|
||||
return NewShortString<allowGC>(cx, TwoByteChars(s, n));
|
||||
|
||||
jschar *news = cx->pod_malloc<jschar>(n + 1);
|
||||
if (!news)
|
||||
return NULL;
|
||||
js_strncpy(news, s, n);
|
||||
news[n] = 0;
|
||||
JSFlatString *str = js_NewString(cx, news, n);
|
||||
JSFlatString *str = js_NewString<allowGC>(cx, news, n);
|
||||
if (!str)
|
||||
js_free(news);
|
||||
return str;
|
||||
}
|
||||
|
||||
template JSFlatString *
|
||||
js_NewStringCopyN<CanGC>(JSContext *cx, const jschar *s, size_t n);
|
||||
|
||||
template JSFlatString *
|
||||
js_NewStringCopyN<NoGC>(JSContext *cx, const jschar *s, size_t n);
|
||||
|
||||
template <AllowGC allowGC>
|
||||
JSFlatString *
|
||||
js_NewStringCopyN(JSContext *cx, const char *s, size_t n)
|
||||
{
|
||||
if (JSShortString::lengthFits(n))
|
||||
return NewShortString(cx, Latin1Chars(s, n));
|
||||
return NewShortString<allowGC>(cx, Latin1Chars(s, n));
|
||||
|
||||
jschar *chars = InflateString(cx, s, &n);
|
||||
if (!chars)
|
||||
return NULL;
|
||||
JSFlatString *str = js_NewString(cx, chars, n);
|
||||
JSFlatString *str = js_NewString<allowGC>(cx, chars, n);
|
||||
if (!str)
|
||||
js_free(chars);
|
||||
return str;
|
||||
}
|
||||
|
||||
template JSFlatString *
|
||||
js_NewStringCopyN<CanGC>(JSContext *cx, const char *s, size_t n);
|
||||
|
||||
template JSFlatString *
|
||||
js_NewStringCopyN<NoGC>(JSContext *cx, const char *s, size_t n);
|
||||
|
||||
template <AllowGC allowGC>
|
||||
JSFlatString *
|
||||
js_NewStringCopyZ(JSContext *cx, const jschar *s)
|
||||
{
|
||||
size_t n = js_strlen(s);
|
||||
if (JSShortString::lengthFits(n))
|
||||
return NewShortString(cx, TwoByteChars(s, n));
|
||||
return NewShortString<allowGC>(cx, TwoByteChars(s, n));
|
||||
|
||||
size_t m = (n + 1) * sizeof(jschar);
|
||||
jschar *news = (jschar *) cx->malloc_(m);
|
||||
if (!news)
|
||||
return NULL;
|
||||
js_memcpy(news, s, m);
|
||||
JSFlatString *str = js_NewString(cx, news, n);
|
||||
JSFlatString *str = js_NewString<allowGC>(cx, news, n);
|
||||
if (!str)
|
||||
js_free(news);
|
||||
return str;
|
||||
}
|
||||
|
||||
template JSFlatString *
|
||||
js_NewStringCopyZ<CanGC>(JSContext *cx, const jschar *s);
|
||||
|
||||
template JSFlatString *
|
||||
js_NewStringCopyZ<NoGC>(JSContext *cx, const jschar *s);
|
||||
|
||||
template <AllowGC allowGC>
|
||||
JSFlatString *
|
||||
js_NewStringCopyZ(JSContext *cx, const char *s)
|
||||
{
|
||||
return js_NewStringCopyN(cx, s, strlen(s));
|
||||
return js_NewStringCopyN<allowGC>(cx, s, strlen(s));
|
||||
}
|
||||
|
||||
template JSFlatString *
|
||||
js_NewStringCopyZ<CanGC>(JSContext *cx, const char *s);
|
||||
|
||||
template JSFlatString *
|
||||
js_NewStringCopyZ<NoGC>(JSContext *cx, const char *s);
|
||||
|
||||
const char *
|
||||
js_ValueToPrintable(JSContext *cx, const Value &v, JSAutoByteString *bytes, bool asSource)
|
||||
{
|
||||
@ -3574,6 +3609,7 @@ js_ValueToPrintable(JSContext *cx, const Value &v, JSAutoByteString *bytes, bool
|
||||
return bytes->encode(cx, str);
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
JSString *
|
||||
js::ToStringSlow(JSContext *cx, const Value &arg)
|
||||
{
|
||||
@ -3581,16 +3617,20 @@ js::ToStringSlow(JSContext *cx, const Value &arg)
|
||||
JS_ASSERT(!arg.isString());
|
||||
|
||||
Value v = arg;
|
||||
if (!ToPrimitive(cx, JSTYPE_STRING, &v))
|
||||
return NULL;
|
||||
if (!v.isPrimitive()) {
|
||||
if (!allowGC)
|
||||
return NULL;
|
||||
if (!ToPrimitive(cx, JSTYPE_STRING, &v))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSString *str;
|
||||
if (v.isString()) {
|
||||
str = v.toString();
|
||||
} else if (v.isInt32()) {
|
||||
str = Int32ToString(cx, v.toInt32());
|
||||
str = Int32ToString<allowGC>(cx, v.toInt32());
|
||||
} else if (v.isDouble()) {
|
||||
str = js_NumberToString(cx, v.toDouble());
|
||||
str = js_NumberToString<allowGC>(cx, v.toDouble());
|
||||
} else if (v.isBoolean()) {
|
||||
str = js_BooleanToString(cx, v.toBoolean());
|
||||
} else if (v.isNull()) {
|
||||
@ -3601,6 +3641,12 @@ js::ToStringSlow(JSContext *cx, const Value &arg)
|
||||
return str;
|
||||
}
|
||||
|
||||
template JSString *
|
||||
js::ToStringSlow<CanGC>(JSContext *cx, const Value &arg);
|
||||
|
||||
template JSString *
|
||||
js::ToStringSlow<NoGC>(JSContext *cx, const Value &arg);
|
||||
|
||||
JSString *
|
||||
js::ValueToSource(JSContext *cx, const Value &v)
|
||||
{
|
||||
@ -3617,7 +3663,7 @@ js::ValueToSource(JSContext *cx, const Value &v)
|
||||
/* NB: _ucNstr rather than _ucstr to indicate non-terminated. */
|
||||
static const jschar js_negzero_ucNstr[] = {'-', '0'};
|
||||
|
||||
return js_NewStringCopyN(cx, js_negzero_ucNstr, 2);
|
||||
return js_NewStringCopyN<CanGC>(cx, js_negzero_ucNstr, 2);
|
||||
}
|
||||
return ToString(cx, v);
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ extern const char js_decodeURIComponent_str[];
|
||||
extern const char js_encodeURIComponent_str[];
|
||||
|
||||
/* GC-allocate a string descriptor for the given malloc-allocated chars. */
|
||||
template <js::AllowGC allowGC>
|
||||
extern JSStableString *
|
||||
js_NewString(JSContext *cx, jschar *chars, size_t length);
|
||||
|
||||
@ -92,16 +93,20 @@ extern JSLinearString *
|
||||
js_NewDependentString(JSContext *cx, JSString *base, size_t start, size_t length);
|
||||
|
||||
/* Copy a counted string and GC-allocate a descriptor for it. */
|
||||
template <js::AllowGC allowGC>
|
||||
extern JSFlatString *
|
||||
js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n);
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
extern JSFlatString *
|
||||
js_NewStringCopyN(JSContext *cx, const char *s, size_t n);
|
||||
|
||||
/* Copy a C string and GC-allocate a descriptor for it. */
|
||||
template <js::AllowGC allowGC>
|
||||
extern JSFlatString *
|
||||
js_NewStringCopyZ(JSContext *cx, const jschar *s);
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
extern JSFlatString *
|
||||
js_NewStringCopyZ(JSContext *cx, const char *s);
|
||||
|
||||
@ -118,6 +123,7 @@ namespace js {
|
||||
* Convert a non-string value to a string, returning null after reporting an
|
||||
* error, otherwise returning a new string reference.
|
||||
*/
|
||||
template <AllowGC allowGC>
|
||||
extern JSString *
|
||||
ToStringSlow(JSContext *cx, const Value &v);
|
||||
|
||||
@ -139,7 +145,7 @@ ToString(JSContext *cx, const js::Value &v)
|
||||
|
||||
if (v.isString())
|
||||
return v.toString();
|
||||
return ToStringSlow(cx, v);
|
||||
return ToStringSlow<CanGC>(cx, v);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1286,7 +1286,7 @@ class TypedArrayTemplate
|
||||
if (ValueIsSpecial(obj, &idval, &sid, cx))
|
||||
return obj_getSpecial(cx, obj, receiver, sid, vp);
|
||||
|
||||
JSAtom *atom = ToAtom(cx, idval);
|
||||
JSAtom *atom = ToAtom<CanGC>(cx, idval);
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
|
@ -383,7 +383,7 @@ ConvertQNameToString(JSContext *cx, JSObject *obj)
|
||||
}
|
||||
js_strncpy(chars + 1, strChars, length);
|
||||
chars[++length] = 0;
|
||||
str = js_NewString(cx, chars, length);
|
||||
str = js_NewString<CanGC>(cx, chars, length);
|
||||
if (!str) {
|
||||
js_free(chars);
|
||||
return NULL;
|
||||
@ -739,7 +739,7 @@ QNameHelper(JSContext *cx, int argc, jsval *argv, jsval *rval)
|
||||
} else if (argc < 0) {
|
||||
name = cx->names().undefined;
|
||||
} else {
|
||||
name = ToAtom(cx, nameval);
|
||||
name = ToAtom<CanGC>(cx, nameval);
|
||||
if (!name)
|
||||
return false;
|
||||
}
|
||||
@ -1234,7 +1234,7 @@ ParseNodeToQName(Parser *parser, ParseNode *pn,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
localName = AtomizeChars(parser->context, colon + 1, length - (offset + 1));
|
||||
localName = AtomizeChars<CanGC>(parser->context, colon + 1, length - (offset + 1));
|
||||
if (!localName)
|
||||
return NULL;
|
||||
} else {
|
||||
@ -1473,7 +1473,7 @@ ParseNodeToXML(Parser *parser, ParseNode *pn,
|
||||
/* 10.3.2.1. Step 6(h)(i)(1)(a). */
|
||||
prefix = cx->runtime->emptyString;
|
||||
} else {
|
||||
prefix = js_NewStringCopyN(cx, chars + 6, length - 6);
|
||||
prefix = js_NewStringCopyN<CanGC>(cx, chars + 6, length - 6);
|
||||
if (!prefix)
|
||||
goto fail;
|
||||
}
|
||||
@ -2270,7 +2270,7 @@ GeneratePrefix(JSContext *cx, JSLinearString *uri, JSXMLArray<JSObject> *decls)
|
||||
* This is necessary for various log10 uses below to be valid.
|
||||
*/
|
||||
if (decls->length == 0)
|
||||
return js_NewStringCopyZ(cx, "a");
|
||||
return js_NewStringCopyZ<CanGC>(cx, "a");
|
||||
|
||||
/*
|
||||
* Try peeling off the last filename suffix or pathname component till
|
||||
@ -2352,7 +2352,7 @@ GeneratePrefix(JSContext *cx, JSLinearString *uri, JSXMLArray<JSObject> *decls)
|
||||
offset = cp - start;
|
||||
prefix = js_NewDependentString(cx, uri, offset, length);
|
||||
} else {
|
||||
prefix = js_NewString(cx, bp, newlength);
|
||||
prefix = js_NewString<CanGC>(cx, bp, newlength);
|
||||
if (!prefix)
|
||||
js_free(bp);
|
||||
}
|
||||
@ -2777,7 +2777,7 @@ ToAttributeName(JSContext *cx, jsval v)
|
||||
|
||||
JSAtom *name;
|
||||
if (JSVAL_IS_STRING(v)) {
|
||||
name = ToAtom(cx, v);
|
||||
name = ToAtom<CanGC>(cx, v);
|
||||
if (!name)
|
||||
return NULL;
|
||||
uri = prefix = cx->runtime->emptyString;
|
||||
@ -2803,7 +2803,7 @@ ToAttributeName(JSContext *cx, jsval v)
|
||||
if (clasp == &AnyNameClass) {
|
||||
name = cx->names().star;
|
||||
} else {
|
||||
name = ToAtom(cx, v);
|
||||
name = ToAtom<CanGC>(cx, v);
|
||||
if (!name)
|
||||
return NULL;
|
||||
}
|
||||
@ -2874,12 +2874,12 @@ ToXMLName(JSContext *cx, jsval v, jsid *funidp)
|
||||
name = cx->names().star;
|
||||
goto construct;
|
||||
}
|
||||
name = ToStringSlow(cx, v);
|
||||
name = ToStringSlow<CanGC>(cx, v);
|
||||
if (!name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
atomizedName = AtomizeString(cx, name);
|
||||
atomizedName = AtomizeString<CanGC>(cx, name);
|
||||
if (!atomizedName)
|
||||
return NULL;
|
||||
|
||||
@ -4588,7 +4588,7 @@ HasFunctionProperty(JSContext *cx, JSObject *obj_, jsid funid_, JSBool *found)
|
||||
Rooted<JSObject*> obj(cx, obj_);
|
||||
RootedObject pobj(cx);
|
||||
RootedShape prop(cx);
|
||||
if (!baseops::LookupProperty(cx, obj, funid, &pobj, &prop))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, obj, funid, &pobj, &prop))
|
||||
return false;
|
||||
if (!prop) {
|
||||
xml = (JSXML *) obj->getPrivate();
|
||||
@ -4601,7 +4601,7 @@ HasFunctionProperty(JSContext *cx, JSObject *obj_, jsid funid_, JSBool *found)
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
if (!baseops::LookupProperty(cx, proto, funid, &pobj, &prop))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, proto, funid, &pobj, &prop))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -4708,7 +4708,7 @@ xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||
if (!qn)
|
||||
return JS_FALSE;
|
||||
if (!JSID_IS_VOID(funid))
|
||||
return baseops::LookupProperty(cx, obj, funid, objp, propp);
|
||||
return baseops::LookupProperty<CanGC>(cx, obj, funid, objp, propp);
|
||||
found = HasNamedProperty(xml, qn);
|
||||
}
|
||||
if (!found) {
|
||||
@ -5217,7 +5217,7 @@ js_TestXMLEquality(JSContext *cx, const Value &v1, const Value &v2, JSBool *bp)
|
||||
vxml->xml_class == JSXML_CLASS_ATTRIBUTE) &&
|
||||
HasSimpleContent(xml)))
|
||||
{
|
||||
ok = (str = ToStringSlow(cx, ObjectValue(*obj))) &&
|
||||
ok = (str = ToStringSlow<CanGC>(cx, ObjectValue(*obj))) &&
|
||||
(vstr = ToString(cx, v));
|
||||
if (ok) {
|
||||
bool equal;
|
||||
@ -5537,7 +5537,7 @@ ValueToIdForXML(JSContext *cx, jsval v, jsid *idp)
|
||||
*idp = id;
|
||||
}
|
||||
} else if (JSVAL_IS_STRING(v)) {
|
||||
JSAtom *atom = AtomizeString(cx, JSVAL_TO_STRING(v));
|
||||
JSAtom *atom = AtomizeString<CanGC>(cx, JSVAL_TO_STRING(v));
|
||||
if (!atom)
|
||||
return JS_FALSE;
|
||||
*idp = AtomToId(atom);
|
||||
@ -5894,7 +5894,7 @@ xml_hasOwnProperty(JSContext *cx, unsigned argc, jsval *vp)
|
||||
|
||||
RootedObject obj2(cx);
|
||||
RootedShape prop(cx);
|
||||
if (!js_HasOwnProperty(cx, baseops::LookupProperty, obj, id, &obj2, &prop))
|
||||
if (!js_HasOwnProperty(cx, baseops::LookupProperty<CanGC>, obj, id, &obj2, &prop))
|
||||
return false;
|
||||
args.rval().setBoolean(!!prop);
|
||||
return true;
|
||||
@ -6648,7 +6648,7 @@ xml_setLocalName(JSContext *cx, unsigned argc, jsval *vp)
|
||||
if (!JSVAL_IS_PRIMITIVE(name) && JSVAL_TO_OBJECT(name)->isQName()) {
|
||||
namestr = JSVAL_TO_OBJECT(name)->getQNameLocalName();
|
||||
} else {
|
||||
namestr = ToAtom(cx, name);
|
||||
namestr = ToAtom<CanGC>(cx, name);
|
||||
if (!namestr)
|
||||
return false;
|
||||
}
|
||||
@ -7613,7 +7613,7 @@ js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, JSString *str2)
|
||||
*newchars++ = '"';
|
||||
}
|
||||
*newchars = 0;
|
||||
return js_NewString(cx, newchars - newlen, newlen);
|
||||
return js_NewString<CanGC>(cx, newchars - newlen, newlen);
|
||||
}
|
||||
|
||||
JSFlatString *
|
||||
@ -7996,7 +7996,7 @@ js_NewXMLSpecialObject(JSContext *cx, JSXMLClass xml_class, JSString *name,
|
||||
return NULL;
|
||||
xml = (JSXML *) obj->getPrivate();
|
||||
if (name) {
|
||||
JSAtom *atomName = AtomizeString(cx, name);
|
||||
JSAtom *atomName = AtomizeString<CanGC>(cx, name);
|
||||
if (!atomName)
|
||||
return NULL;
|
||||
qn = NewXMLQName(cx, cx->runtime->emptyString, NULL, atomName);
|
||||
|
@ -472,9 +472,8 @@ StubEqualityOp(VMFrame &f)
|
||||
JSContext *cx = f.cx;
|
||||
FrameRegs ®s = f.regs;
|
||||
|
||||
RootedValue rval_(cx, regs.sp[-1]);
|
||||
RootedValue lval_(cx, regs.sp[-2]);
|
||||
Value &rval = rval_.get(), &lval = lval_.get();
|
||||
Value &rval = regs.sp[-1];
|
||||
Value &lval = regs.sp[-2];
|
||||
|
||||
bool cond;
|
||||
|
||||
|
@ -3589,7 +3589,7 @@ GetSelfHostedValue(JSContext *cx, unsigned argc, jsval *vp)
|
||||
"getSelfHostedValue");
|
||||
return false;
|
||||
}
|
||||
RootedAtom srcAtom(cx, ToAtom(cx, args[0]));
|
||||
RootedAtom srcAtom(cx, ToAtom<CanGC>(cx, args[0]));
|
||||
if (!srcAtom)
|
||||
return false;
|
||||
RootedPropertyName srcName(cx, srcAtom->asPropertyName());
|
||||
|
@ -349,7 +349,7 @@ args_enumerate(JSContext *cx, HandleObject obj)
|
||||
|
||||
RootedObject pobj(cx);
|
||||
RootedShape prop(cx);
|
||||
if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, argsobj, id, &pobj, &prop))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -467,22 +467,22 @@ strictargs_enumerate(JSContext *cx, HandleObject obj)
|
||||
|
||||
// length
|
||||
id = NameToId(cx->names().length);
|
||||
if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, argsobj, id, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
// callee
|
||||
id = NameToId(cx->names().callee);
|
||||
if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, argsobj, id, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
// caller
|
||||
id = NameToId(cx->names().caller);
|
||||
if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, argsobj, id, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0, argc = argsobj->initialLength(); i < argc; i++) {
|
||||
id = INT_TO_JSID(i);
|
||||
if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop))
|
||||
if (!baseops::LookupProperty<CanGC>(cx, argsobj, id, &pobj, &prop))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2758,7 +2758,7 @@ DebuggerScript_getUrl(JSContext *cx, unsigned argc, Value *vp)
|
||||
THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "(get url)", args, obj, script);
|
||||
|
||||
if (script->filename) {
|
||||
JSString *str = js_NewStringCopyZ(cx, script->filename);
|
||||
JSString *str = js_NewStringCopyZ<CanGC>(cx, script->filename);
|
||||
if (!str)
|
||||
return false;
|
||||
args.rval().setString(str);
|
||||
@ -4201,7 +4201,7 @@ DebuggerObject_getOwnPropertyNames(JSContext *cx, unsigned argc, Value *vp)
|
||||
for (size_t i = 0, len = keys.length(); i < len; i++) {
|
||||
jsid id = keys[i];
|
||||
if (JSID_IS_INT(id)) {
|
||||
JSString *str = Int32ToString(cx, JSID_TO_INT(id));
|
||||
JSString *str = Int32ToString<CanGC>(cx, JSID_TO_INT(id));
|
||||
if (!str)
|
||||
return false;
|
||||
vals[i].setString(str);
|
||||
|
@ -249,7 +249,7 @@ RegExpObject *
|
||||
RegExpObject::createNoStatics(JSContext *cx, StableCharPtr chars, size_t length, RegExpFlag flags,
|
||||
TokenStream *tokenStream)
|
||||
{
|
||||
RootedAtom source(cx, AtomizeChars(cx, chars.get(), length));
|
||||
RootedAtom source(cx, AtomizeChars<CanGC>(cx, chars.get(), length));
|
||||
if (!source)
|
||||
return NULL;
|
||||
|
||||
|
@ -309,7 +309,7 @@ CloneObject(JSContext *cx, HandleObject srcObj, CloneMemory &clonedObjects)
|
||||
Rooted<JSStableString*> str(cx, srcObj->asString().unbox()->ensureStable(cx));
|
||||
if (!str)
|
||||
return NULL;
|
||||
str = js_NewStringCopyN(cx, str->chars().get(), str->length())->ensureStable(cx);
|
||||
str = js_NewStringCopyN<CanGC>(cx, str->chars().get(), str->length())->ensureStable(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
clone = StringObject::create(cx, str);
|
||||
@ -343,7 +343,7 @@ CloneValue(JSContext *cx, MutableHandleValue vp, CloneMemory &clonedObjects)
|
||||
Rooted<JSStableString*> str(cx, vp.toString()->ensureStable(cx));
|
||||
if (!str)
|
||||
return false;
|
||||
RootedString clone(cx, js_NewStringCopyN(cx, str->chars().get(), str->length()));
|
||||
RootedString clone(cx, js_NewStringCopyN<CanGC>(cx, str->chars().get(), str->length()));
|
||||
if (!clone)
|
||||
return false;
|
||||
vp.setString(clone);
|
||||
|
@ -21,14 +21,15 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static JS_ALWAYS_INLINE JSInlineString *
|
||||
NewShortString(JSContext *cx, Latin1Chars chars)
|
||||
{
|
||||
size_t len = chars.length();
|
||||
JS_ASSERT(JSShortString::lengthFits(len));
|
||||
UnrootedInlineString str = JSInlineString::lengthFits(len)
|
||||
? JSInlineString::new_<ALLOW_GC>(cx)
|
||||
: JSShortString::new_<ALLOW_GC>(cx);
|
||||
? JSInlineString::new_<allowGC>(cx)
|
||||
: JSShortString::new_<allowGC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
@ -40,6 +41,7 @@ NewShortString(JSContext *cx, Latin1Chars chars)
|
||||
return str;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static JS_ALWAYS_INLINE JSInlineString *
|
||||
NewShortString(JSContext *cx, StableTwoByteChars chars)
|
||||
{
|
||||
@ -51,8 +53,8 @@ NewShortString(JSContext *cx, StableTwoByteChars chars)
|
||||
*/
|
||||
JS_ASSERT(JSShortString::lengthFits(len));
|
||||
JSInlineString *str = JSInlineString::lengthFits(len)
|
||||
? JSInlineString::new_<ALLOW_GC>(cx)
|
||||
: JSShortString::new_<ALLOW_GC>(cx);
|
||||
? JSInlineString::new_<allowGC>(cx)
|
||||
: JSShortString::new_<allowGC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
@ -63,6 +65,7 @@ NewShortString(JSContext *cx, StableTwoByteChars chars)
|
||||
return str;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static JS_ALWAYS_INLINE JSInlineString *
|
||||
NewShortString(JSContext *cx, TwoByteChars chars)
|
||||
{
|
||||
@ -74,12 +77,14 @@ NewShortString(JSContext *cx, TwoByteChars chars)
|
||||
*/
|
||||
JS_ASSERT(JSShortString::lengthFits(len));
|
||||
JSInlineString *str = JSInlineString::lengthFits(len)
|
||||
? JSInlineString::new_<DONT_ALLOW_GC>(cx)
|
||||
: JSShortString::new_<DONT_ALLOW_GC>(cx);
|
||||
? JSInlineString::new_<NoGC>(cx)
|
||||
: JSShortString::new_<NoGC>(cx);
|
||||
if (!str) {
|
||||
if (!allowGC)
|
||||
return NULL;
|
||||
jschar tmp[JSShortString::MAX_SHORT_LENGTH];
|
||||
PodCopy(tmp, chars.start().get(), len);
|
||||
return NewShortString(cx, StableTwoByteChars(tmp, len));
|
||||
return NewShortString<CanGC>(cx, StableTwoByteChars(tmp, len));
|
||||
}
|
||||
|
||||
jschar *storage = str->init(len);
|
||||
@ -179,10 +184,10 @@ JSRope::init(JSString *left, JSString *right, size_t length)
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
JS_ALWAYS_INLINE JSRope *
|
||||
JSRope::newStringMaybeAllowGC(JSContext *cx,
|
||||
typename js::MaybeRooted<JSString*, allowGC>::HandleType left,
|
||||
typename js::MaybeRooted<JSString*, allowGC>::HandleType right,
|
||||
size_t length)
|
||||
JSRope::new_(JSContext *cx,
|
||||
typename js::MaybeRooted<JSString*, allowGC>::HandleType left,
|
||||
typename js::MaybeRooted<JSString*, allowGC>::HandleType right,
|
||||
size_t length)
|
||||
{
|
||||
if (!validateLength(cx, length))
|
||||
return NULL;
|
||||
@ -241,9 +246,9 @@ JSDependentString::new_(JSContext *cx, JSLinearString *baseArg, const jschar *ch
|
||||
* is more efficient to immediately undepend here.
|
||||
*/
|
||||
if (JSShortString::lengthFits(length))
|
||||
return js::NewShortString(cx, js::TwoByteChars(chars, length));
|
||||
return js::NewShortString<js::CanGC>(cx, js::TwoByteChars(chars, length));
|
||||
|
||||
JSDependentString *str = (JSDependentString *)js_NewGCString<js::ALLOW_GC>(cx);
|
||||
JSDependentString *str = (JSDependentString *)js_NewGCString<js::CanGC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
str->init(base, chars, length);
|
||||
@ -266,7 +271,7 @@ JSFlatString::toPropertyName(JSContext *cx)
|
||||
#endif
|
||||
if (isAtom())
|
||||
return asAtom().asPropertyName();
|
||||
JSAtom *atom = js::AtomizeString(cx, this);
|
||||
JSAtom *atom = js::AtomizeString<js::CanGC>(cx, this);
|
||||
if (!atom)
|
||||
return NULL;
|
||||
return atom->asPropertyName();
|
||||
@ -286,6 +291,7 @@ JSStableString::init(const jschar *chars, size_t length)
|
||||
d.u1.chars = chars;
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
JS_ALWAYS_INLINE JSStableString *
|
||||
JSStableString::new_(JSContext *cx, const jschar *chars, size_t length)
|
||||
{
|
||||
@ -293,7 +299,7 @@ JSStableString::new_(JSContext *cx, const jschar *chars, size_t length)
|
||||
|
||||
if (!validateLength(cx, length))
|
||||
return NULL;
|
||||
JSStableString *str = (JSStableString *)js_NewGCString<js::ALLOW_GC>(cx);
|
||||
JSStableString *str = (JSStableString *)js_NewGCString<allowGC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
str->init(chars, length);
|
||||
|
@ -336,23 +336,20 @@ ConcatStringsMaybeAllowGC(JSContext *cx,
|
||||
return str;
|
||||
}
|
||||
|
||||
return JSRope::newStringMaybeAllowGC<allowGC>(cx, left, right, wholeLength);
|
||||
return JSRope::new_<allowGC>(cx, left, right, wholeLength);
|
||||
}
|
||||
|
||||
JSString *
|
||||
js_ConcatStrings(JSContext *cx, HandleString left, HandleString right)
|
||||
{
|
||||
return ConcatStringsMaybeAllowGC<ALLOW_GC>(cx, left, right);
|
||||
return ConcatStringsMaybeAllowGC<CanGC>(cx, left, right);
|
||||
}
|
||||
|
||||
JSString *
|
||||
js::ConcatStringsNoGC(JSContext *cx, JSString *left, JSString *right)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
JSString *res = ConcatStringsMaybeAllowGC<DONT_ALLOW_GC>(cx, left, right);
|
||||
|
||||
JS_ASSERT(!cx->isExceptionPending());
|
||||
return res;
|
||||
AutoAssertNoGCOrException nogc(cx);
|
||||
return ConcatStringsMaybeAllowGC<NoGC>(cx, left, right);
|
||||
}
|
||||
|
||||
JSFlatString *
|
||||
@ -491,7 +488,7 @@ StaticStrings::init(JSContext *cx)
|
||||
|
||||
for (uint32_t i = 0; i < UNIT_STATIC_LIMIT; i++) {
|
||||
jschar buffer[] = { jschar(i), '\0' };
|
||||
JSFlatString *s = js_NewStringCopyN(cx, buffer, 1);
|
||||
JSFlatString *s = js_NewStringCopyN<CanGC>(cx, buffer, 1);
|
||||
if (!s)
|
||||
return false;
|
||||
unitStaticTable[i] = s->morphAtomizedStringIntoAtom();
|
||||
@ -499,7 +496,7 @@ StaticStrings::init(JSContext *cx)
|
||||
|
||||
for (uint32_t i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++) {
|
||||
jschar buffer[] = { FROM_SMALL_CHAR(i >> 6), FROM_SMALL_CHAR(i & 0x3F), '\0' };
|
||||
JSFlatString *s = js_NewStringCopyN(cx, buffer, 2);
|
||||
JSFlatString *s = js_NewStringCopyN<CanGC>(cx, buffer, 2);
|
||||
if (!s)
|
||||
return false;
|
||||
length2StaticTable[i] = s->morphAtomizedStringIntoAtom();
|
||||
@ -517,7 +514,7 @@ StaticStrings::init(JSContext *cx)
|
||||
jschar('0' + ((i / 10) % 10)),
|
||||
jschar('0' + (i % 10)),
|
||||
'\0' };
|
||||
JSFlatString *s = js_NewStringCopyN(cx, buffer, 3);
|
||||
JSFlatString *s = js_NewStringCopyN<CanGC>(cx, buffer, 3);
|
||||
if (!s)
|
||||
return false;
|
||||
intStaticTable[i] = s->morphAtomizedStringIntoAtom();
|
||||
|
@ -447,11 +447,10 @@ class JSRope : public JSString
|
||||
|
||||
public:
|
||||
template <js::AllowGC allowGC>
|
||||
static inline JSRope *
|
||||
newStringMaybeAllowGC(JSContext *cx,
|
||||
typename js::MaybeRooted<JSString*, allowGC>::HandleType left,
|
||||
typename js::MaybeRooted<JSString*, allowGC>::HandleType right,
|
||||
size_t length);
|
||||
static inline JSRope *new_(JSContext *cx,
|
||||
typename js::MaybeRooted<JSString*, allowGC>::HandleType left,
|
||||
typename js::MaybeRooted<JSString*, allowGC>::HandleType right,
|
||||
size_t length);
|
||||
|
||||
inline JSString *leftChild() const {
|
||||
JS_ASSERT(isRope());
|
||||
@ -560,6 +559,7 @@ class JSStableString : public JSFlatString
|
||||
void init(const jschar *chars, size_t length);
|
||||
|
||||
public:
|
||||
template <js::AllowGC allowGC>
|
||||
static inline JSStableString *new_(JSContext *cx, const jschar *chars, size_t length);
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
|
@ -51,7 +51,7 @@ StringBuffer::finishString()
|
||||
|
||||
JS_STATIC_ASSERT(JSShortString::MAX_SHORT_LENGTH < CharBuffer::InlineLength);
|
||||
if (JSShortString::lengthFits(length))
|
||||
return NewShortString(cx, TwoByteChars(cb.begin(), length));
|
||||
return NewShortString<CanGC>(cx, TwoByteChars(cb.begin(), length));
|
||||
|
||||
if (!cb.append('\0'))
|
||||
return UnrootedFlatString();
|
||||
@ -60,7 +60,7 @@ StringBuffer::finishString()
|
||||
if (!buf)
|
||||
return UnrootedFlatString();
|
||||
|
||||
JSFlatString *str = js_NewString(cx, buf, length);
|
||||
JSFlatString *str = js_NewString<CanGC>(cx, buf, length);
|
||||
if (!str)
|
||||
js_free(buf);
|
||||
return str;
|
||||
@ -76,7 +76,7 @@ StringBuffer::finishAtom()
|
||||
if (length == 0)
|
||||
return UnrootedAtom(cx->names().empty);
|
||||
|
||||
UnrootedAtom atom = AtomizeChars(cx, cb.begin(), length);
|
||||
UnrootedAtom atom = AtomizeChars<CanGC>(cx, cb.begin(), length);
|
||||
cb.clear();
|
||||
return atom;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user