Bug 834242 - Reduce cost of exact stack rooting during property reads, r=terrence.

This commit is contained in:
Brian Hackett 2013-01-24 20:18:34 -07:00
parent c511765584
commit ca7794f586
59 changed files with 678 additions and 402 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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 {

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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 {

View File

@ -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)));

View File

@ -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);

View File

@ -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 *)

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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>

View File

@ -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);

View File

@ -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())

View File

@ -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(&regs.sp[-2]);
MutableHandleValue rval = MutableHandleValue::fromMarkedLocation(&regs.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(&regs.sp[-2]);
MutableHandleValue rval = MutableHandleValue::fromMarkedLocation(&regs.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(&regs.sp[-2]);
MutableHandleValue rval = MutableHandleValue::fromMarkedLocation(&regs.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(&regs.sp[-2]);
MutableHandleValue rval = MutableHandleValue::fromMarkedLocation(&regs.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);
}

View File

@ -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,

View File

@ -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(>=);
}

View File

@ -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;

View File

@ -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);

View File

@ -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) {
/*

View File

@ -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,

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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++);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}
/*

View File

@ -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;

View File

@ -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);

View File

@ -472,9 +472,8 @@ StubEqualityOp(VMFrame &f)
JSContext *cx = f.cx;
FrameRegs &regs = 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;

View File

@ -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());

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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

View File

@ -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;
}