Add most handles and stack rooters needed for exact scanning on shell benchmarks, bug 714647. r=billm

This commit is contained in:
Brian Hackett 2012-04-12 09:23:51 -07:00
Родитель ecd67863cd
Коммит 5fe350f0a8
81 изменённых файлов: 1306 добавлений и 1025 удалений

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

@ -226,6 +226,7 @@ EXPORTS_ds = \
EXPORTS_gc = \
Statistics.h \
Barrier.h \
Root.h \
$(NULL)
######################################################

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

@ -54,7 +54,7 @@ using namespace js::types;
class RegExpMatchBuilder
{
JSContext * const cx;
JSObject * const array;
RootedVarObject array;
bool setProperty(JSAtom *name, Value v) {
return !!js_DefineProperty(cx, array, ATOM_TO_JSID(name), &v,
@ -62,7 +62,7 @@ class RegExpMatchBuilder
}
public:
RegExpMatchBuilder(JSContext *cx, JSObject *array) : cx(cx), array(array) {}
RegExpMatchBuilder(JSContext *cx, JSObject *array) : cx(cx), array(cx, array) {}
bool append(uint32_t index, Value v) {
JS_ASSERT(!array->getOps()->getElement);
@ -81,9 +81,11 @@ class RegExpMatchBuilder
};
static bool
CreateRegExpMatchResult(JSContext *cx, JSString *input, const jschar *chars, size_t length,
CreateRegExpMatchResult(JSContext *cx, JSString *input_, const jschar *chars, size_t length,
MatchPairs *matchPairs, Value *rval)
{
RootedVarString input(cx, input_);
/*
* Create the (slow) result array for a match.
*
@ -93,7 +95,7 @@ CreateRegExpMatchResult(JSContext *cx, JSString *input, const jschar *chars, siz
* input: input string
* index: start index for the match
*/
JSObject *array = NewSlowEmptyArray(cx);
RootedVarObject array(cx, NewSlowEmptyArray(cx));
if (!array)
return false;
@ -225,7 +227,8 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
{
if (args.length() == 0) {
RegExpStatics *res = cx->regExpStatics();
RegExpObject *reobj = builder.build(cx->runtime->emptyString, res->getFlags());
RegExpObject *reobj = builder.build(RootedVarAtom(cx, cx->runtime->emptyString),
res->getFlags());
if (!reobj)
return false;
args.rval() = ObjectValue(*reobj);
@ -272,7 +275,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
if (!sourceObj.getProperty(cx, cx->runtime->atomState.sourceAtom, &v))
return false;
RegExpObject *reobj = builder.build(&v.toString()->asAtom(), flags);
RegExpObject *reobj = builder.build(RootedVarAtom(cx, &v.toString()->asAtom()), flags);
if (!reobj)
return false;
@ -304,7 +307,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
return false;
}
JSAtom *escapedSourceStr = EscapeNakedForwardSlashes(cx, source);
RootedVarAtom escapedSourceStr(cx, EscapeNakedForwardSlashes(cx, source));
if (!escapedSourceStr)
return false;
@ -482,22 +485,22 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = &obj->asGlobal();
RootedVar<GlobalObject*> global(cx, &obj->asGlobal());
JSObject *proto = global->createBlankPrototype(cx, &RegExpClass);
RootedVarObject proto(cx, global->createBlankPrototype(cx, &RegExpClass));
if (!proto)
return NULL;
proto->setPrivate(NULL);
RegExpObject *reproto = &proto->asRegExp();
RegExpObjectBuilder builder(cx, reproto);
if (!builder.build(cx->runtime->emptyString, RegExpFlag(0)))
RegExpObjectBuilder builder(cx, &proto->asRegExp());
if (!builder.build(RootedVarAtom(cx, cx->runtime->emptyString), RegExpFlag(0)))
return NULL;
if (!DefinePropertiesAndBrand(cx, proto, NULL, regexp_methods))
return NULL;
JSFunction *ctor = global->createConstructor(cx, regexp_construct, CLASS_ATOM(cx, RegExp), 2);
RootedVarFunction ctor(cx);
ctor = global->createConstructor(cx, regexp_construct, CLASS_ATOM(cx, RegExp), 2);
if (!ctor)
return NULL;
@ -575,14 +578,14 @@ ExecuteRegExp(JSContext *cx, Native native, unsigned argc, Value *vp)
if (!obj)
return ok;
RegExpObject &reobj = obj->asRegExp();
RootedVar<RegExpObject*> reobj(cx, &obj->asRegExp());
RegExpGuard re;
if (StartsWithGreedyStar(reobj.getSource())) {
if (!GetSharedForGreedyStar(cx, reobj.getSource(), reobj.getFlags(), &re))
if (StartsWithGreedyStar(reobj->getSource())) {
if (!GetSharedForGreedyStar(cx, reobj->getSource(), reobj->getFlags(), &re))
return false;
} else {
if (!reobj.getShared(cx, &re))
if (!reobj->getShared(cx, &re))
return false;
}
@ -601,7 +604,7 @@ ExecuteRegExp(JSContext *cx, Native native, unsigned argc, Value *vp)
size_t length = input->length();
/* Step 4. */
const Value &lastIndex = reobj.getLastIndex();
const Value &lastIndex = reobj->getLastIndex();
/* Step 5. */
double i;
@ -614,7 +617,7 @@ ExecuteRegExp(JSContext *cx, Native native, unsigned argc, Value *vp)
/* Step 9a. */
if (i < 0 || i > length) {
reobj.zeroLastIndex();
reobj->zeroLastIndex();
args.rval() = NullValue();
return true;
}
@ -630,9 +633,9 @@ ExecuteRegExp(JSContext *cx, Native native, unsigned argc, Value *vp)
/* Step 11 (with sticky extension). */
if (re->global() || (!args.rval().isNull() && re->sticky())) {
if (args.rval().isNull())
reobj.zeroLastIndex();
reobj->zeroLastIndex();
else
reobj.setLastIndex(lastIndexInt);
reobj->setLastIndex(lastIndexInt);
}
return true;

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

@ -4155,7 +4155,7 @@ fi
dnl ========================================================
dnl = Perform moving GC stack rooting analysis
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(gcrootanalysis,
MOZ_ARG_ENABLE_BOOL(root-analysis,
[ --enable-root-analysis Enable moving GC stack root analysis],
JSGC_ROOT_ANALYSIS=1,
JSGC_ROOT_ANALYSIS= )

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

@ -53,9 +53,11 @@ using namespace js;
using namespace js::frontend;
bool
DefineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *script)
DefineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript* script)
{
JSObject *globalObj = globalScope.globalObj;
Root<JSScript*> root(cx, &script);
HandleObject globalObj = globalScope.globalObj;
/* Define and update global properties. */
for (size_t i = 0; i < globalScope.defs.length(); i++) {
@ -165,7 +167,6 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
{
TokenKind tt;
ParseNode *pn;
JSScript *script;
bool inDirectivePrologue;
JS_ASSERT(!(tcflags & ~(TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL | TCF_COMPILE_FOR_EVAL
@ -199,8 +200,7 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
JS_ASSERT_IF(globalObj, globalObj->isNative());
JS_ASSERT_IF(globalObj, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalObj->getClass()));
/* Null script early in case of error, to reduce our code footprint. */
script = NULL;
RootedVar<JSScript*> script(cx);
GlobalScope globalScope(cx, globalObj, &bce);
bce.flags |= tcflags;

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

@ -49,8 +49,9 @@ namespace js {
inline
TreeContext::TreeContext(Parser *prs)
: flags(0), bodyid(0), blockidGen(0), parenDepth(0), yieldCount(0),
topStmt(NULL), topScopeStmt(NULL), blockChain(NULL), blockNode(NULL),
decls(prs->context), parser(prs), yieldNode(NULL), argumentsNode(NULL), scopeChain_(NULL),
topStmt(NULL), topScopeStmt(NULL), blockChain(prs->context), blockNode(NULL),
decls(prs->context), parser(prs), yieldNode(NULL), argumentsNode(NULL),
fun_(prs->context), scopeChain_(prs->context),
lexdeps(prs->context), parent(prs->tc), staticLevel(0), funbox(NULL), functionList(NULL),
innermostWith(NULL), bindings(prs->context), bindingsRoot(prs->context, &bindings),
funcStmts(NULL)

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

@ -423,7 +423,7 @@ frontend::PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_
stmt->blockid = tc->blockid();
SET_STATEMENT_TOP(stmt, top);
stmt->label = NULL;
JS_ASSERT(!stmt->blockObj);
stmt->blockObj = NULL;
stmt->down = tc->topStmt;
tc->topStmt = stmt;
if (STMT_LINKS_SCOPE(stmt)) {
@ -1360,7 +1360,6 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
Definition *dn;
JSOp op;
JSAtom *atom;
Definition::Kind dn_kind;
JS_ASSERT(pn->isKind(PNK_NAME));
@ -1394,7 +1393,7 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return JS_TRUE;
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
atom = pn->pn_atom;
RootedVarAtom atom(cx, pn->pn_atom);
UpvarCookie cookie = dn->pn_cookie;
dn_kind = dn->kind();
@ -2369,7 +2368,7 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
int noteIndex;
size_t switchSize, tableSize;
jsbytecode *pc, *savepc;
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
/* Try for most optimal, fall back if not dense ints, and per ECMAv2. */
switchOp = JSOP_TABLESWITCH;
@ -3982,7 +3981,7 @@ ParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp)
JS_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
gc::AllocKind kind = GuessObjectGCKind(pn_count);
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
RootedVarObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass, kind));
if (!obj)
return false;
@ -4141,7 +4140,7 @@ EmitCatch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
MOZ_NEVER_INLINE static bool
EmitTry(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
ptrdiff_t catchJump = -1;
/*
@ -4373,7 +4372,7 @@ EmitTry(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
static bool
EmitIf(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
/* Initialize so we can detect else-if chains and avoid recursion. */
stmtInfo.type = STMT_IF;
@ -4530,7 +4529,7 @@ EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
return false;
}
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
PushBlockScope(bce, &stmtInfo, blockObj, bce->offset());
if (!letNotes.update(cx, bce, bce->offset()))
@ -4656,7 +4655,7 @@ EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
JS_ASSERT(pn->isKind(PNK_LEXICALSCOPE));
JS_ASSERT(pn->getOp() == JSOP_LEAVEBLOCK);
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
ObjectBox *objbox = pn->pn_objbox;
StaticBlockObject &blockObj = objbox->object->asStaticBlock();
PushBlockScope(bce, &stmtInfo, blockObj, bce->offset());
@ -4705,7 +4704,7 @@ EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
static bool
EmitWith(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
if (!EmitTree(cx, bce, pn->pn_left))
return false;
PushStatement(bce, &stmtInfo, STMT_WITH, bce->offset());
@ -4722,7 +4721,7 @@ EmitWith(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
static bool
EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
PushStatement(bce, &stmtInfo, STMT_FOR_IN_LOOP, top);
ParseNode *forHead = pn->pn_left;
@ -4788,7 +4787,7 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
return false;
/* Enter the block before the loop body, after evaluating the obj. */
StmtInfo letStmt;
StmtInfo letStmt(cx);
if (letDecl) {
PushBlockScope(bce, &letStmt, *blockObj, bce->offset());
letStmt.flags |= SIF_FOR_BLOCK;
@ -4898,7 +4897,7 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
static bool
EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
PushStatement(bce, &stmtInfo, STMT_FOR_LOOP, top);
ParseNode *forHead = pn->pn_left;
@ -5055,7 +5054,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return Emit1(cx, bce, JSOP_GETFUNNS) >= 0;
#endif
JSFunction *fun = pn->pn_funbox->function();
RootedVarFunction fun(cx, pn->pn_funbox->function());
JS_ASSERT(fun->isInterpreted());
if (fun->script()) {
/*
@ -5178,7 +5177,7 @@ EmitDo(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (!EmitLoopEntry(cx, bce, NULL))
return false;
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
PushStatement(bce, &stmtInfo, STMT_DO_LOOP, top);
if (!EmitTree(cx, bce, pn->pn_left))
return false;
@ -5231,7 +5230,7 @@ EmitWhile(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
* . . .
* N N*(ifeq-fail; goto); ifeq-pass goto; N*ifne-pass; ifne-fail
*/
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
PushStatement(bce, &stmtInfo, STMT_WHILE_LOOP, top);
ptrdiff_t noteIndex = NewSrcNote(cx, bce, SRC_WHILE);
@ -5369,7 +5368,7 @@ EmitStatementList(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t
return false;
}
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
PushStatement(bce, &stmtInfo, STMT_BLOCK, top);
ParseNode *pnchild = pn->pn_head;
@ -5850,7 +5849,7 @@ EmitLabel(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return false;
/* Emit code for the labeled statement. */
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
PushStatement(bce, &stmtInfo, STMT_LABEL, bce->offset());
stmtInfo.label = atom;
if (!EmitTree(cx, bce, pn2))
@ -5874,7 +5873,7 @@ static bool
EmitSyntheticStatements(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
JS_ASSERT(pn->isArity(PN_LIST));
StmtInfo stmtInfo;
StmtInfo stmtInfo(cx);
PushStatement(bce, &stmtInfo, STMT_SEQ, top);
for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
if (!EmitTree(cx, bce, pn2))
@ -5950,7 +5949,7 @@ EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* Try to construct the shape of the object as we go, so we can emit a
* JSOP_NEWOBJECT with the final shape instead.
*/
JSObject *obj = NULL;
RootedVarObject obj(cx);
if (bce->compileAndGo()) {
gc::AllocKind kind = GuessObjectGCKind(pn->pn_count);
obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);

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

@ -54,6 +54,8 @@
#include "frontend/Parser.h"
#include "frontend/ParseMaps.h"
#include "vm/ScopeObject.h"
namespace js {
typedef HashSet<JSAtom *> FuncStmtSet;
@ -136,12 +138,12 @@ struct StmtInfo {
ptrdiff_t update; /* loop update offset (top if none) */
ptrdiff_t breaks; /* offset of last break in loop */
ptrdiff_t continues; /* offset of last continue in loop */
union {
JSAtom *label; /* name of LABEL */
StaticBlockObject *blockObj;/* block scope object */
};
RootedVarAtom label; /* name of LABEL */
RootedVar<StaticBlockObject *> blockObj; /* block scope object */
StmtInfo *down; /* info for enclosing statement */
StmtInfo *downScope; /* next enclosing lexical scope */
StmtInfo(JSContext *cx) : label(cx), blockObj(cx) {}
};
#define SIF_SCOPE 0x0001 /* statement has its own lexical scope */
@ -336,7 +338,8 @@ struct TreeContext { /* tree context for semantic checks */
non-zero depth in current paren tree */
StmtInfo *topStmt; /* top of statement info stack */
StmtInfo *topScopeStmt; /* top lexical scope statement */
StaticBlockObject *blockChain; /* compile block scope chain (NB: one
RootedVar<StaticBlockObject *> blockChain;
/* compile time block scope chain (NB: one
deeper than the topScopeStmt/downScope
chain when in head of let block/expr) */
ParseNode *blockNode; /* parse node for a block with let declarations
@ -351,11 +354,9 @@ struct TreeContext { /* tree context for semantic checks */
inside a generator expression */
private:
union {
JSFunction *fun_; /* function to store argument and variable
RootedVarFunction fun_; /* function to store argument and variable
names when flags & TCF_IN_FUNCTION */
JSObject *scopeChain_; /* scope chain object for the script */
};
RootedVarObject scopeChain_; /* scope chain object for the script */
public:
JSFunction *fun() const {
@ -544,7 +545,8 @@ class GCConstList {
struct GlobalScope {
GlobalScope(JSContext *cx, JSObject *globalObj, BytecodeEmitter *bce)
: globalObj(globalObj), bce(bce), defs(cx), names(cx)
: globalObj(cx, globalObj), bce(bce), defs(cx), names(cx),
defsRoot(cx, &defs), namesRoot(cx, &names)
{ }
struct GlobalDef {
@ -558,7 +560,7 @@ struct GlobalScope {
GlobalDef(JSAtom *atom, FunctionBox *box) : atom(atom), funbox(box) { }
};
JSObject *globalObj;
RootedVarObject globalObj;
BytecodeEmitter *bce;
/*
@ -571,6 +573,13 @@ struct GlobalScope {
*/
Vector<GlobalDef, 16> defs;
AtomIndexMap names;
/*
* Protect the inline elements within defs/names from being clobbered by
* root analysis. The atoms in this structure must be separately rooted.
*/
JS::SkipRoot defsRoot;
JS::SkipRoot namesRoot;
};
struct BytecodeEmitter : public TreeContext

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

@ -230,8 +230,8 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
ParseNodeKind kind = pn->getKind();
ParseNode **pnp = &pn->pn_head;
ParseNode *pn1 = *pnp;
JSString *accum = NULL;
JSString *str = NULL;
RootedVarString accum(cx);
RootedVarString str(cx);
if ((pn->pn_xflags & PNX_CANTFOLD) == 0) {
if (kind == PNK_XMLETAGO)
accum = cx->runtime->atomState.etagoAtom;
@ -745,15 +745,13 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
/* Handle a binary string concatenation. */
JS_ASSERT(pn->isArity(PN_BINARY));
if (pn1->isKind(PNK_STRING) || pn2->isKind(PNK_STRING)) {
JSString *left, *right, *str;
if (!FoldType(cx, !pn1->isKind(PNK_STRING) ? pn1 : pn2, PNK_STRING))
return false;
if (!pn1->isKind(PNK_STRING) || !pn2->isKind(PNK_STRING))
return true;
left = pn1->pn_atom;
right = pn2->pn_atom;
str = js_ConcatStrings(cx, left, right);
RootedVarString left(cx, pn1->pn_atom);
RootedVarString right(cx, pn2->pn_atom);
RootedVarString str(cx, js_ConcatStrings(cx, left, right));
if (!str)
return false;
pn->pn_atom = js_AtomizeString(cx, str);

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

@ -174,6 +174,8 @@ Parser::setPrincipals(JSPrincipals *prin, JSPrincipals *originPrin)
ObjectBox *
Parser::newObjectBox(JSObject *obj)
{
JS_ASSERT(obj && !IsPoisonedPtr(obj));
/*
* We use JSContext.tempLifoAlloc to allocate parsed objects and place them
* on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
@ -197,7 +199,7 @@ Parser::newObjectBox(JSObject *obj)
FunctionBox *
Parser::newFunctionBox(JSObject *obj, ParseNode *fn, TreeContext *tc)
{
JS_ASSERT(obj);
JS_ASSERT(obj && !IsPoisonedPtr(obj));
JS_ASSERT(obj->isFunction());
/*
@ -583,7 +585,7 @@ BindLocalVariable(JSContext *cx, TreeContext *tc, ParseNode *pn, BindingKind kin
JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
unsigned index = tc->bindings.numVars();
if (!tc->bindings.add(cx, pn->pn_atom, kind))
if (!tc->bindings.add(cx, RootedVarAtom(cx, pn->pn_atom), kind))
return false;
pn->pn_cookie.set(tc->staticLevel, index);
@ -596,7 +598,7 @@ Parser::functionBody(FunctionBodyType type)
{
JS_ASSERT(tc->inFunction());
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
PushStatement(tc, &stmtInfo, STMT_BLOCK, -1);
stmtInfo.flags = SIF_BODY_BLOCK;
@ -646,7 +648,7 @@ Parser::functionBody(FunctionBodyType type)
if (!CheckStrictParameters(context, tc))
return NULL;
PropertyName * const arguments = context->runtime->atomState.argumentsAtom;
RootedVar<PropertyName*> const arguments(context, context->runtime->atomState.argumentsAtom);
/*
* Non-top-level functions use JSOP_DEFFUN which is a dynamic scope
@ -1354,7 +1356,7 @@ Parser::functionArguments(TreeContext &funtc, FunctionBox *funbox, ParseNode **l
case TOK_NAME:
{
PropertyName *name = tokenStream.currentToken().name();
RootedVar<PropertyName*> name(context, tokenStream.currentToken().name());
#ifdef JS_HAS_DESTRUCTURING
/*
@ -1414,7 +1416,7 @@ Parser::functionArguments(TreeContext &funtc, FunctionBox *funbox, ParseNode **l
}
ParseNode *
Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind kind)
Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSyntaxKind kind)
{
JS_ASSERT_IF(kind == Statement, funName);
@ -1537,7 +1539,7 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind
if (!funbox)
return NULL;
JSFunction *fun = funbox->function();
RootedVarFunction fun(context, funbox->function());
/* Now parse formal argument list and compute fun->nargs. */
ParseNode *prelude = NULL;
@ -1727,7 +1729,7 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind
ParseNode *
Parser::functionStmt()
{
PropertyName *name = NULL;
RootedVarPropertyName name(context);
if (tokenStream.getToken(TSF_KEYWORD_IS_NAME) == TOK_NAME) {
name = tokenStream.currentToken().name();
} else {
@ -1748,7 +1750,7 @@ Parser::functionStmt()
ParseNode *
Parser::functionExpr()
{
PropertyName *name = NULL;
RootedVarPropertyName name(context);
if (tokenStream.getToken(TSF_KEYWORD_IS_NAME) == TOK_NAME)
name = tokenStream.currentToken().name();
else
@ -1968,8 +1970,8 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc)
if (!CheckStrictBinding(cx, tc, atom->asPropertyName(), pn))
return false;
StaticBlockObject &blockObj = *data->let.blockObj;
unsigned blockCount = blockObj.slotCount();
RootedVar<StaticBlockObject *> blockObj(cx, data->let.blockObj);
unsigned blockCount = blockObj->slotCount();
if (blockCount == JS_BIT(16)) {
ReportCompileErrorNumber(cx, TS(tc->parser), pn,
JSREPORT_ERROR, data->let.overflow);
@ -2006,7 +2008,7 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc)
*/
bool redeclared;
jsid id = ATOM_TO_JSID(atom);
const Shape *shape = blockObj.addVar(cx, id, blockCount, &redeclared);
const Shape *shape = blockObj->addVar(cx, id, blockCount, &redeclared);
if (!shape) {
if (redeclared)
ReportRedeclaration(cx, tc, pn, false, atom);
@ -2014,7 +2016,7 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc)
}
/* Store pn in the static block object. */
blockObj.setDefinitionParseNode(blockCount, reinterpret_cast<Definition *>(pn));
blockObj->setDefinitionParseNode(blockCount, reinterpret_cast<Definition *>(pn));
return true;
}
@ -2085,11 +2087,12 @@ static bool
DefineGlobal(ParseNode *pn, BytecodeEmitter *bce, PropertyName *name)
{
GlobalScope *globalScope = bce->globalScope;
JSObject *globalObj = globalScope->globalObj;
HandleObject globalObj = globalScope->globalObj;
if (!bce->compileAndGo() || !globalObj || bce->compilingForEval())
return true;
JS_ASSERT(!IsPoisonedPtr(name));
AtomIndexAddPtr p = globalScope->names.lookupForAdd(name);
if (!p) {
JSContext *cx = bce->parser->context;
@ -2127,6 +2130,8 @@ DefineGlobal(ParseNode *pn, BytecodeEmitter *bce, PropertyName *name)
if (!globalScope->defs.append(def))
return false;
JS_ASSERT(!IsPoisonedPtr(name));
jsatomid index = globalScope->names.count();
if (!globalScope->names.add(p, name, index))
return false;
@ -2591,7 +2596,8 @@ CheckDestructuring(JSContext *cx, BindData *data, ParseNode *left, TreeContext *
return false;
}
StaticBlockObject *blockObj = data && data->binder == BindLet ? data->let.blockObj : NULL;
RootedVar<StaticBlockObject *> blockObj(cx);
blockObj = data && data->binder == BindLet ? data->let.blockObj : NULL;
uint32_t blockCountBefore = blockObj ? blockObj->slotCount() : 0;
if (left->isKind(PNK_RB)) {
@ -2902,7 +2908,7 @@ Parser::letBlock(LetContext letContext)
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_LET);
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
ParseNode *block = PushLetScope(context, tc, *blockObj, &stmtInfo);
if (!block)
return NULL;
@ -3037,7 +3043,7 @@ Parser::switchStatement()
* NB: we must push stmtInfo before calling GenerateBlockIdForStmtNode
* because that function states tc->topStmt->blockid.
*/
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
PushStatement(tc, &stmtInfo, STMT_SWITCH, -1);
/* pn2 is a list of case nodes. The default case has pn_left == NULL */
@ -3159,7 +3165,7 @@ Parser::forStatement()
if (!pn)
return NULL;
StmtInfo forStmt;
StmtInfo forStmt(context);
PushStatement(tc, &forStmt, STMT_FOR_LOOP, -1);
pn->setOp(JSOP_ITER);
@ -3251,9 +3257,9 @@ Parser::forStatement()
* as we've excluded 'in' from being parsed in RelExpr by setting
* the TCF_IN_FOR_INIT flag in our TreeContext.
*/
ParseNode *forHead; /* initialized by both branches. */
StmtInfo letStmt; /* used if blockObj != NULL. */
ParseNode *pn2, *pn3; /* forHead->pn_kid1 and pn_kid2. */
ParseNode *forHead; /* initialized by both branches. */
StmtInfo letStmt(context); /* used if blockObj != NULL. */
ParseNode *pn2, *pn3; /* forHead->pn_kid1 and pn_kid2. */
bool forOf;
if (pn1 && matchInOrOf(&forOf)) {
/*
@ -3552,7 +3558,7 @@ Parser::tryStatement()
pn->setOp(JSOP_NOP);
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY);
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
if (!PushBlocklikeStatement(&stmtInfo, STMT_TRY, tc))
return NULL;
pn->pn_kid1 = statements();
@ -3719,7 +3725,7 @@ Parser::withStatement()
ParseNode *oldWith = tc->innermostWith;
tc->innermostWith = pn;
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
PushStatement(tc, &stmtInfo, STMT_WITH, -1);
pn2 = statement();
if (!pn2)
@ -3890,7 +3896,7 @@ Parser::expressionStatement()
(void) tokenStream.getToken();
/* Push a label struct and parse the statement. */
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
PushStatement(tc, &stmtInfo, STMT_LABEL, -1);
stmtInfo.label = label;
ParseNode *pn = statement();
@ -3971,7 +3977,7 @@ Parser::statement()
if (!pn1)
return NULL;
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
PushStatement(tc, &stmtInfo, STMT_IF, -1);
ParseNode *pn2 = statement();
if (!pn2)
@ -4010,7 +4016,7 @@ Parser::statement()
pn = BinaryNode::create(PNK_WHILE, tc);
if (!pn)
return NULL;
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
PushStatement(tc, &stmtInfo, STMT_WHILE_LOOP, -1);
ParseNode *pn2 = condition();
if (!pn2)
@ -4030,7 +4036,7 @@ Parser::statement()
pn = BinaryNode::create(PNK_DOWHILE, tc);
if (!pn)
return NULL;
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
PushStatement(tc, &stmtInfo, STMT_DO_LOOP, -1);
ParseNode *pn2 = statement();
if (!pn2)
@ -4207,7 +4213,7 @@ Parser::statement()
oldflags = tc->flags;
tc->flags = oldflags & ~TCF_HAS_FUNCTION_STMT;
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
if (!PushBlocklikeStatement(&stmtInfo, STMT_BLOCK, tc))
return NULL;
pn = statements();
@ -5308,7 +5314,7 @@ Parser::comprehensionTail(ParseNode *kid, unsigned blockid, bool isGenexp,
{
unsigned adjust;
ParseNode *pn, *pn2, *pn3, **pnp;
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
BindData data;
TokenKind tt;
@ -5757,7 +5763,7 @@ Parser::memberExpr(JSBool allowCallSyntax)
tc->flags |= TCF_FUN_HEAVYWEIGHT;
tc->noteBindingsAccessedDynamically();
StmtInfo stmtInfo;
StmtInfo stmtInfo(context);
ParseNode *oldWith = tc->innermostWith;
tc->innermostWith = lhs;
PushStatement(tc, &stmtInfo, STMT_WITH, -1);
@ -6934,7 +6940,8 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
pn->pn_xflags |= PNX_NONCONST;
/* NB: Getter function in { get x(){} } is unnamed. */
pn2 = functionDef(NULL, op == JSOP_GETTER ? Getter : Setter, Expression);
pn2 = functionDef(RootedVarPropertyName(context, NULL),
op == JSOP_GETTER ? Getter : Setter, Expression);
if (!pn2)
return NULL;
TokenPos pos = {begin, pn2->pn_pos.end};
@ -7147,7 +7154,7 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
RegExpFlag flags = tokenStream.currentToken().regExpFlags();
RegExpStatics *res = context->regExpStatics();
RegExpObject *reobj;
RootedVar<RegExpObject*> reobj(context);
if (context->hasfp())
reobj = RegExpObject::create(context, res, chars, length, flags, &tokenStream);
else

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

@ -243,7 +243,7 @@ struct Parser : private AutoGCRooter
enum FunctionType { Getter, Setter, Normal };
bool functionArguments(TreeContext &funtc, FunctionBox *funbox, ParseNode **list);
ParseNode *functionDef(PropertyName *name, FunctionType type, FunctionSyntaxKind kind);
ParseNode *functionDef(HandlePropertyName name, FunctionType type, FunctionSyntaxKind kind);
ParseNode *unaryOpExpr(ParseNodeKind kind, JSOp op);

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

@ -154,7 +154,8 @@ js::IsIdentifier(JSLinearString *str)
/* Initialize members that aren't initialized in |init|. */
TokenStream::TokenStream(JSContext *cx, JSPrincipals *prin, JSPrincipals *originPrin)
: tokens(), cursor(), lookahead(), flags(), listenerTSData(), tokenbuf(cx),
: tokens(), tokensRoot(cx, &tokens),
cursor(), lookahead(), flags(), userbufRoot(cx, &userbuf), listenerTSData(), tokenbuf(cx),
cx(cx), originPrincipals(JSScript::normalizeOriginPrincipals(prin, originPrin))
{
if (originPrincipals)

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

@ -336,12 +336,14 @@ struct Token {
void setName(JSOp op, PropertyName *name) {
JS_ASSERT(op == JSOP_NAME);
JS_ASSERT(!IsPoisonedPtr(name));
u.s.op = op;
u.s.n.name = name;
}
void setAtom(JSOp op, JSAtom *atom) {
JS_ASSERT(op == JSOP_STRING || op == JSOP_XMLCOMMENT || JSOP_XMLCDATA);
JS_ASSERT(!IsPoisonedPtr(atom));
u.s.op = op;
u.s.n.atom = atom;
}
@ -350,6 +352,8 @@ struct Token {
JS_ASSERT(target);
JS_ASSERT(data);
JS_ASSERT(!target->empty());
JS_ASSERT(!IsPoisonedPtr(target));
JS_ASSERT(!IsPoisonedPtr(data));
u.xmlpi.target = target;
u.xmlpi.data = data;
}
@ -808,13 +812,15 @@ class TokenStream
void updateFlagsForEOL();
Token tokens[ntokens];/* circular token buffer */
unsigned cursor; /* index of last parsed token */
unsigned lookahead; /* count of lookahead tokens */
unsigned lineno; /* current line number */
unsigned flags; /* flags -- see above */
JS::SkipRoot tokensRoot; /* prevent overwriting of token buffer */
unsigned cursor; /* index of last parsed token */
unsigned lookahead; /* count of lookahead tokens */
unsigned lineno; /* current line number */
unsigned flags; /* flags -- see above */
const jschar *linebase; /* start of current line; points into userbuf */
const jschar *prevLinebase; /* start of previous line; NULL if on the first line */
TokenBuf userbuf; /* user input buffer */
JS::SkipRoot userbufRoot; /* prevent overwriting of char pointers within userbuf */
const char *filename; /* input filename or null */
jschar *sourceMap; /* source map's filename or null */
void *listenerTSData;/* listener data for this TokenStream */

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

@ -124,6 +124,7 @@ HeapValue::init(const Value &v)
inline void
HeapValue::init(JSCompartment *comp, const Value &v)
{
JS_ASSERT(!IsPoisonedValue(v));
value = v;
post(comp);
}

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

@ -40,10 +40,11 @@
#ifndef jsgc_root_h__
#define jsgc_root_h__
#include "jsapi.h"
#include "jsprvtd.h"
#include "jspubtd.h"
namespace js {
#ifdef __cplusplus
namespace JS {
/*
* Moving GC Stack Rooting
@ -92,33 +93,55 @@ namespace js {
* fix than when relying on a separate rooting analysis.
*/
template <> struct RootMethods<const jsid>
template <typename T> class Root;
template <typename T> class RootedVar;
template <typename T>
struct RootMethods { };
/*
* Reference to a stack location rooted for GC. See "Moving GC Stack Rooting"
* comment in jscntxt.h.
*/
template <typename T>
class Handle
{
static jsid initial() { return JSID_VOID; }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(jsid id) { return IsPoisonedId(id); }
public:
/* Copy handles of different types, with implicit coercion. */
template <typename S> Handle(Handle<S> handle) {
testAssign<S>();
ptr = reinterpret_cast<const T *>(handle.address());
}
/* Get a handle from a rooted stack location, with implicit coercion. */
template <typename S> inline Handle(const Root<S> &root);
template <typename S> inline Handle(const RootedVar<S> &root);
const T *address() { return ptr; }
operator T () { return value(); }
T operator ->() { return value(); }
private:
const T *ptr;
T value() { return *ptr; }
template <typename S>
void testAssign() {
#ifdef DEBUG
T a = RootMethods<T>::initial();
S b = RootMethods<S>::initial();
a = b;
(void)a;
#endif
}
};
template <> struct RootMethods<jsid>
{
static jsid initial() { return JSID_VOID; }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(jsid id) { return IsPoisonedId(id); }
};
template <> struct RootMethods<const Value>
{
static Value initial() { return UndefinedValue(); }
static ThingRootKind kind() { return THING_ROOT_VALUE; }
static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
};
template <> struct RootMethods<Value>
{
static Value initial() { return UndefinedValue(); }
static ThingRootKind kind() { return THING_ROOT_VALUE; }
static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
};
typedef Handle<JSObject*> HandleObject;
typedef Handle<JSFunction*> HandleFunction;
typedef Handle<JSString*> HandleString;
typedef Handle<jsid> HandleId;
typedef Handle<Value> HandleValue;
template <typename T>
struct RootMethods<T *>
@ -142,10 +165,12 @@ template <typename T>
class Root
{
public:
Root(JSContext *cx, const T *ptr
Root(JSContext *cx_, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
#ifdef JSGC_ROOT_ANALYSIS
ContextFriendFields *cx = ContextFriendFields::get(cx_);
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Root<T>**>(&cx->thingGCRooters[kind]);
this->prev = *stack;
@ -191,53 +216,58 @@ Handle<T>::Handle(const Root<S> &root)
ptr = reinterpret_cast<const T *>(root.address());
}
typedef Root<JSObject*> RootObject;
typedef Root<JSFunction*> RootFunction;
typedef Root<Shape*> RootShape;
typedef Root<BaseShape*> RootBaseShape;
typedef Root<types::TypeObject*> RootTypeObject;
typedef Root<JSString*> RootString;
typedef Root<JSAtom*> RootAtom;
typedef Root<jsid> RootId;
typedef Root<Value> RootValue;
typedef Root<JSObject*> RootObject;
typedef Root<JSFunction*> RootFunction;
typedef Root<JSString*> RootString;
typedef Root<jsid> RootId;
typedef Root<Value> RootValue;
/* Mark a stack location as a root for a rooting analysis. */
class CheckRoot
/*
* Mark a stack location as a root for the rooting analysis, without actually
* rooting it in release builds. This should only be used for stack locations
* of GC things that cannot be relocated by a garbage collection, and that
* are definitely reachable via another path.
*/
class SkipRoot
{
#if defined(DEBUG) && defined(JSGC_ROOT_ANALYSIS)
CheckRoot **stack, *prev;
const uint8_t *ptr;
SkipRoot **stack, *prev;
const uint8_t *start;
const uint8_t *end;
public:
template <typename T>
CheckRoot(JSContext *cx, const T *ptr
SkipRoot(JSContext *cx_, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
this->stack = &cx->checkGCRooters;
ContextFriendFields *cx = ContextFriendFields::get(cx_);
this->stack = &cx->skipGCRooters;
this->prev = *stack;
*stack = this;
this->ptr = static_cast<const uint8_t*>(ptr);
this->start = (const uint8_t *) ptr;
this->end = this->start + sizeof(T);
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
~CheckRoot()
~SkipRoot()
{
JS_ASSERT(*stack == this);
*stack = prev;
}
CheckRoot *previous() { return prev; }
SkipRoot *previous() { return prev; }
bool contains(const uint8_t *v, size_t len) {
return ptr >= v && ptr < v + len;
return v >= start && v + len <= end;
}
#else /* DEBUG && JSGC_ROOT_ANALYSIS */
public:
template <typename T>
CheckRoot(JSContext *cx, const T *ptr
SkipRoot(JSContext *cx, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
@ -261,10 +291,14 @@ class RootedVar
: ptr(initial), root(cx, &ptr)
{}
operator T () { return ptr; }
T operator ->() { return ptr; }
RootedVar() MOZ_DELETE;
RootedVar(const RootedVar &) MOZ_DELETE;
operator T () const { return ptr; }
T operator ->() const { return ptr; }
T * address() { return &ptr; }
const T * address() const { return &ptr; }
T & reference() { return ptr; }
T raw() { return ptr; }
T & operator =(T value)
@ -274,6 +308,12 @@ class RootedVar
return ptr;
}
T & operator =(const RootedVar &value)
{
ptr = value;
return ptr;
}
private:
T ptr;
Root<T> root;
@ -286,15 +326,14 @@ Handle<T>::Handle(const RootedVar<S> &root)
ptr = reinterpret_cast<const T *>(root.address());
}
typedef RootedVar<JSObject*> RootedVarObject;
typedef RootedVar<JSFunction*> RootedVarFunction;
typedef RootedVar<Shape*> RootedVarShape;
typedef RootedVar<BaseShape*> RootedVarBaseShape;
typedef RootedVar<types::TypeObject*> RootedVarTypeObject;
typedef RootedVar<JSString*> RootedVarString;
typedef RootedVar<JSAtom*> RootedVarAtom;
typedef RootedVar<jsid> RootedVarId;
typedef RootedVar<Value> RootedVarValue;
typedef RootedVar<JSObject*> RootedVarObject;
typedef RootedVar<JSFunction*> RootedVarFunction;
typedef RootedVar<JSString*> RootedVarString;
typedef RootedVar<jsid> RootedVarId;
typedef RootedVar<Value> RootedVarValue;
} /* namespace JS */
#endif /* __cplusplus */
} /* namespace js */
#endif /* jsgc_root_h___ */

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

@ -3079,7 +3079,7 @@ JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
{
JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
JS_ASSERT(obj);
return DefaultValue(cx, obj, type, vp);
return DefaultValue(cx, RootedVarObject(cx, obj), type, vp);
}
JS_PUBLIC_API(JSObject *)
@ -3619,7 +3619,7 @@ JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *obj, const jschar *name, siz
}
static JSBool
DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, const Value &value,
DefinePropertyById(JSContext *cx, HandleObject obj, jsid id, const Value &value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int tinyid)
{
@ -3679,16 +3679,18 @@ DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, const Value &value,
}
JS_PUBLIC_API(JSBool)
JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
JS_DefinePropertyById(JSContext *cx, JSObject *obj_, jsid id, jsval value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
RootedVarObject obj(cx, obj_);
return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
}
JS_PUBLIC_API(JSBool)
JS_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, jsval value,
JS_DefineElement(JSContext *cx, JSObject *obj_, uint32_t index, jsval value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
RootedVarObject obj(cx, obj_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
jsid id;
@ -3698,15 +3700,15 @@ JS_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, jsval value,
}
static JSBool
DefineProperty(JSContext *cx, JSObject *obj, const char *name, const Value &value,
DefineProperty(JSContext *cx, JSObject *obj_, const char *name, const Value &value_,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int tinyid)
{
jsid id;
JSAtom *atom;
RootObject objRoot(cx, &obj);
RootValue valueRoot(cx, &value);
RootedVarObject obj(cx, obj_);
RootedVarValue value(cx, value_);
if (attrs & JSPROP_INDEX) {
id = INT_TO_JSID(intptr_t(name));
@ -3737,10 +3739,11 @@ JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name, int8
}
static JSBool
DefineUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
DefineUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen,
const Value &value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int tinyid)
{
RootObject obj(cx, &obj_);
JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
return atom && DefinePropertyById(cx, obj, ATOM_TO_JSID(atom), value, getter, setter, attrs,
flags, tinyid);
@ -3768,7 +3771,7 @@ JS_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, jsval descriptor, JS
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id, descriptor);
return js_DefineOwnProperty(cx, obj, id, descriptor, bp);
return js_DefineOwnProperty(cx, RootedVarObject(cx, obj), RootedVarId(cx, id), descriptor, bp);
}
JS_PUBLIC_API(JSObject *)
@ -3797,8 +3800,10 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *jsclasp
}
JS_PUBLIC_API(JSBool)
JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
JS_DefineConstDoubles(JSContext *cx, JSObject *obj_, JSConstDoubleSpec *cds)
{
RootedVarObject obj(cx, obj_);
JSBool ok;
unsigned attrs;
@ -3945,7 +3950,7 @@ JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
AssertNoGC(cx);
CHECK_REQUEST(cx);
return GetOwnPropertyDescriptor(cx, obj, id, vp);
return GetOwnPropertyDescriptor(cx, RootedVarObject(cx, obj), RootedVarId(cx, id), vp);
}
static JSBool
@ -4005,7 +4010,7 @@ JS_ForwardGetPropertyTo(JSContext *cx, JSObject *obj, jsid id, JSObject *onBehal
JS_PUBLIC_API(JSBool)
JS_GetPropertyByIdDefault(JSContext *cx, JSObject *obj, jsid id, jsval def, jsval *vp)
{
return GetPropertyDefault(cx, obj, id, def, vp);
return GetPropertyDefault(cx, RootedVarObject(cx, obj), RootedVarId(cx, id), def, vp);
}
JS_PUBLIC_API(JSBool)
@ -4065,7 +4070,7 @@ JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, jsval *
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
if (!js_GetMethod(cx, obj, id, 0, vp))
if (!js_GetMethod(cx, RootedVarObject(cx, obj), id, 0, vp))
return JS_FALSE;
if (objp)
*objp = obj;
@ -4520,11 +4525,14 @@ JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flag
}
JS_PUBLIC_API(JSObject *)
JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent_)
{
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, parent); // XXX no funobj for now
assertSameCompartment(cx, parent_); // XXX no funobj for now
RootedVarObject parent(cx, parent_);
if (!parent) {
if (cx->hasfp())
parent = &cx->fp()->scopeChain();
@ -4543,7 +4551,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
return NULL;
}
JSFunction *fun = funobj->toFunction();
RootedVarFunction fun(cx, funobj->toFunction());
if (fun->isInterpreted() && fun->script()->compileAndGo) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
@ -5061,10 +5069,8 @@ CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
assertSameCompartment(cx, obj, principals);
AutoLastFrameCheck lfc(cx);
JSAtom *funAtom;
if (!name) {
funAtom = NULL;
} else {
RootedVarAtom funAtom(cx);
if (name) {
funAtom = js_Atomize(cx, name, strlen(name));
if (!funAtom)
return NULL;
@ -5073,7 +5079,7 @@ CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
Bindings bindings(cx);
for (unsigned i = 0; i < nargs; i++) {
uint16_t dummy;
JSAtom *argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]));
RootedVarAtom argAtom(cx, js_Atomize(cx, argnames[i], strlen(argnames[i])));
if (!argAtom || !bindings.addArgument(cx, argAtom, &dummy))
return NULL;
}
@ -5254,7 +5260,7 @@ JS_ExecuteScriptVersion(JSContext *cx, JSObject *obj, JSScript *script, jsval *r
}
bool
EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj_,
JSPrincipals *principals, JSPrincipals *originPrincipals,
const jschar *chars, unsigned length,
const char *filename, unsigned lineno,
@ -5262,6 +5268,8 @@ EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
RootedVarObject obj(cx, obj_);
uint32_t flags = TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL;
if (!rval)
flags |= TCF_NO_SCRIPT_RVAL;
@ -5373,15 +5381,17 @@ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, unsigned argc, js
}
JS_PUBLIC_API(JSBool)
JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, unsigned argc, jsval *argv,
JS_CallFunctionName(JSContext *cx, JSObject *obj_, const char *name, unsigned argc, jsval *argv,
jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, JSValueArray(argv, argc));
assertSameCompartment(cx, obj_, JSValueArray(argv, argc));
AutoLastFrameCheck lfc(cx);
RootedVarObject obj(cx, obj_);
Value v;
JSAtom *atom = js_Atomize(cx, name, strlen(name));
return atom &&
@ -5755,7 +5765,7 @@ JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
{
AssertNoGC(cx);
CHECK_REQUEST(cx);
return js_ConcatStrings(cx, left, right);
return js_ConcatStrings(cx, RootedVarString(cx, left), RootedVarString(cx, right));
}
JS_PUBLIC_API(const jschar *)

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

@ -54,6 +54,7 @@
#include "jsval.h"
#include "js/Utility.h"
#include "gc/Root.h"
#ifdef __cplusplus
#include "jsalloc.h"
@ -769,6 +770,20 @@ SameType(const Value &lhs, const Value &rhs)
return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
}
template <> struct RootMethods<const Value>
{
static Value initial() { return UndefinedValue(); }
static ThingRootKind kind() { return THING_ROOT_VALUE; }
static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
};
template <> struct RootMethods<Value>
{
static Value initial() { return UndefinedValue(); }
static ThingRootKind kind() { return THING_ROOT_VALUE; }
static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
};
/************************************************************************/
#ifndef __GNUC__
@ -1052,7 +1067,7 @@ class AutoVectorRooter : protected AutoGCRooter
public:
explicit AutoVectorRooter(JSContext *cx, ptrdiff_t tag
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, tag), vector(cx)
: AutoGCRooter(cx, tag), vector(cx), vectorRoot(cx, &vector)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
@ -1115,6 +1130,10 @@ class AutoVectorRooter : protected AutoGCRooter
typedef js::Vector<T, 8> VectorImpl;
VectorImpl vector;
/* Prevent overwriting of inline elements in vector. */
SkipRoot vectorRoot;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
@ -2457,6 +2476,8 @@ JS_IsInSuspendedRequest(JSRuntime *rt);
#ifdef __cplusplus
JS_END_EXTERN_C
namespace JS {
inline bool
IsPoisonedId(jsid iden)
{
@ -2467,6 +2488,22 @@ IsPoisonedId(jsid iden)
return false;
}
template <> struct RootMethods<const jsid>
{
static jsid initial() { return JSID_VOID; }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(jsid id) { return IsPoisonedId(id); }
};
template <> struct RootMethods<jsid>
{
static jsid initial() { return JSID_VOID; }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(jsid id) { return IsPoisonedId(id); }
};
} /* namespace JS */
class JSAutoRequest {
public:
JSAutoRequest(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)

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

@ -481,7 +481,7 @@ GetElements(JSContext *cx, JSObject *aobj, uint32_t length, Value *vp)
* Set the value of the property at the given index to v assuming v is rooted.
*/
static JSBool
SetArrayElement(JSContext *cx, JSObject *obj, double index, const Value &v)
SetArrayElement(JSContext *cx, HandleObject obj, double index, const Value &v)
{
JS_ASSERT(index >= 0);
@ -504,7 +504,7 @@ SetArrayElement(JSContext *cx, JSObject *obj, double index, const Value &v)
if (result == JSObject::ED_FAILED)
return false;
JS_ASSERT(result == JSObject::ED_SPARSE);
if (!obj->makeDenseArraySlow(cx))
if (!JSObject::makeDenseArraySlow(cx, obj))
return JS_FALSE;
}
@ -532,7 +532,7 @@ SetArrayElement(JSContext *cx, JSObject *obj, double index, const Value &v)
* - Return -1 if an exception occurs (that is, [[Delete]] would throw).
*/
static int
DeleteArrayElement(JSContext *cx, JSObject *obj, double index, bool strict)
DeleteArrayElement(JSContext *cx, HandleObject obj, double index, bool strict)
{
JS_ASSERT(index >= 0);
JS_ASSERT(floor(index) == index);
@ -567,7 +567,7 @@ DeleteArrayElement(JSContext *cx, JSObject *obj, double index, bool strict)
* its value to v assuming v is rooted.
*/
static JSBool
SetOrDeleteArrayElement(JSContext *cx, JSObject *obj, double index,
SetOrDeleteArrayElement(JSContext *cx, HandleObject obj, double index,
JSBool hole, const Value &v)
{
if (hole) {
@ -606,8 +606,10 @@ array_length_getter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
}
static JSBool
array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
array_length_setter(JSContext *cx, JSObject *obj_, jsid id, JSBool strict, Value *vp)
{
RootedVarObject obj(cx, obj_);
if (!obj->isArray()) {
return obj->defineProperty(cx, cx->runtime->atomState.lengthAtom, *vp,
NULL, NULL, JSPROP_ENUMERATE);
@ -803,7 +805,13 @@ array_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName
}
if (!obj->isDenseArray())
return js_GetProperty(cx, obj, receiver, ATOM_TO_JSID(name), vp);
{
return js_GetProperty(cx,
RootedVarObject(cx, obj),
RootedVarObject(cx, receiver),
ATOM_TO_JSID(name),
vp);
}
JSObject *proto = obj->getProto();
if (!proto) {
@ -818,7 +826,13 @@ static JSBool
array_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp)
{
if (!obj->isDenseArray())
return js_GetElement(cx, obj, receiver, index, vp);
{
return js_GetElement(cx,
RootedVarObject(cx, obj),
RootedVarObject(cx, receiver),
index,
vp);
}
if (index < obj->getDenseArrayInitializedLength()) {
*vp = obj->getDenseArrayElement(index);
@ -848,7 +862,11 @@ array_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid
return true;
}
return js_GetProperty(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
return js_GetProperty(cx,
RootedVarObject(cx, obj),
RootedVarObject(cx, receiver),
SPECIALID_TO_JSID(sid),
vp);
}
static JSBool
@ -894,9 +912,10 @@ array_typeOf(JSContext *cx, JSObject *obj)
}
static JSBool
array_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
array_setGeneric(JSContext *cx, JSObject *obj_, jsid id_, Value *vp, JSBool strict)
{
uint32_t i;
RootedVarObject obj(cx, obj_);
RootedVarId id(cx, id_);
if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
return array_length_setter(cx, obj, id, strict, vp);
@ -905,6 +924,7 @@ array_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict
return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
do {
uint32_t i;
if (!js_IdIsIndex(id, &i))
break;
if (js_PrototypeHasIndexedProperties(cx, obj))
@ -924,7 +944,7 @@ array_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict
return true;
} while (false);
if (!obj->makeDenseArraySlow(cx))
if (!JSObject::makeDenseArraySlow(cx, obj))
return false;
return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
}
@ -936,8 +956,10 @@ array_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, J
}
static JSBool
array_setElement(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict)
array_setElement(JSContext *cx, JSObject *obj_, uint32_t index, Value *vp, JSBool strict)
{
RootedVarObject obj(cx, obj_);
jsid id;
if (!IndexToId(cx, index, &id))
return false;
@ -969,7 +991,7 @@ array_setElement(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool
return true;
} while (false);
if (!obj->makeDenseArraySlow(cx))
if (!JSObject::makeDenseArraySlow(cx, obj))
return false;
return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
}
@ -1003,9 +1025,11 @@ js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj)
}
static JSBool
array_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *value,
array_defineGeneric(JSContext *cx, JSObject *obj_, jsid id, const Value *value,
JSPropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
RootedVarObject obj(cx, obj_);
if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
return JS_TRUE;
@ -1032,7 +1056,7 @@ array_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *value,
return true;
} while (false);
if (!obj->makeDenseArraySlow(cx))
if (!JSObject::makeDenseArraySlow(cx, obj))
return false;
return js_DefineProperty(cx, obj, id, value, getter, setter, attrs);
}
@ -1048,9 +1072,11 @@ namespace js {
/* non-static for direct definition of array elements within the engine */
JSBool
array_defineElement(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
array_defineElement(JSContext *cx, JSObject *obj_, uint32_t index, const Value *value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
RootedVarObject obj(cx, obj_);
if (!obj->isDenseArray())
return js_DefineElement(cx, obj, index, value, getter, setter, attrs);
@ -1080,7 +1106,7 @@ array_defineElement(JSContext *cx, JSObject *obj, uint32_t index, const Value *v
return true;
} while (false);
if (!obj->makeDenseArraySlow(cx))
if (!JSObject::makeDenseArraySlow(cx, obj))
return false;
return js_DefineElement(cx, obj, index, value, getter, setter, attrs);
}
@ -1211,15 +1237,17 @@ array_trace(JSTracer *trc, JSObject *obj)
}
static JSBool
array_fix(JSContext *cx, JSObject *obj, bool *success, AutoIdVector *props)
array_fix(JSContext *cx, JSObject *obj_, bool *success, AutoIdVector *props)
{
RootedVarObject obj(cx, obj_);
JS_ASSERT(obj->isDenseArray());
/*
* We must slowify dense arrays; otherwise, we'd need to detect assignments to holes,
* since that is effectively adding a new property to the array.
*/
if (!obj->makeDenseArraySlow(cx) ||
if (!JSObject::makeDenseArraySlow(cx, obj) ||
!GetPropertyNames(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY, props))
return false;
@ -1352,26 +1380,26 @@ AddLengthProperty(JSContext *cx, JSObject *obj)
/*
* Convert an array object from fast-and-dense to slow-and-flexible.
*/
JSBool
JSObject::makeDenseArraySlow(JSContext *cx)
/* static */ bool
JSObject::makeDenseArraySlow(JSContext *cx, HandleObject obj)
{
JS_ASSERT(isDenseArray());
JS_ASSERT(obj->isDenseArray());
MarkTypeObjectFlags(cx, this,
MarkTypeObjectFlags(cx, obj,
OBJECT_FLAG_NON_PACKED_ARRAY |
OBJECT_FLAG_NON_DENSE_ARRAY);
uint32_t arrayCapacity = getDenseArrayCapacity();
uint32_t arrayInitialized = getDenseArrayInitializedLength();
uint32_t arrayCapacity = obj->getDenseArrayCapacity();
uint32_t arrayInitialized = obj->getDenseArrayInitializedLength();
/*
* Get an allocated array of the existing elements, evicting from the fixed
* slots if necessary.
*/
if (!hasDynamicElements()) {
if (!growElements(cx, arrayCapacity))
if (!obj->hasDynamicElements()) {
if (!obj->growElements(cx, arrayCapacity))
return false;
JS_ASSERT(hasDynamicElements());
JS_ASSERT(obj->hasDynamicElements());
}
/*
@ -1379,19 +1407,19 @@ JSObject::makeDenseArraySlow(JSContext *cx)
* on error. This is gross, but a better way is not obvious. Note: the
* exact contents of the array are not preserved on error.
*/
js::Shape *oldShape = lastProperty();
js::Shape *oldShape = obj->lastProperty();
/* Create a native scope. */
gc::AllocKind kind = getAllocKind();
Shape *shape = EmptyShape::getInitialShape(cx, &SlowArrayClass, getProto(),
gc::AllocKind kind = obj->getAllocKind();
Shape *shape = EmptyShape::getInitialShape(cx, &SlowArrayClass, obj->getProto(),
oldShape->getObjectParent(), kind);
if (!shape)
return false;
this->shape_ = shape;
obj->shape_ = shape;
/* Take ownership of the dense elements, reset to an empty dense array. */
HeapSlot *elems = elements;
elements = emptyObjectElements;
HeapSlot *elems = obj->elements;
obj->elements = emptyObjectElements;
/* Root all values in the array during conversion. */
AutoValueArray autoArray(cx, (Value *) elems, arrayInitialized);
@ -1400,11 +1428,11 @@ JSObject::makeDenseArraySlow(JSContext *cx)
* Begin with the length property to share more of the property tree.
* The getter/setter here will directly access the object's private value.
*/
if (!AddLengthProperty(cx, this)) {
this->shape_ = oldShape;
if (elements != emptyObjectElements)
cx->free_(getElementsHeader());
elements = elems;
if (!AddLengthProperty(cx, obj)) {
obj->shape_ = oldShape;
if (obj->elements != emptyObjectElements)
cx->free_(obj->getElementsHeader());
obj->elements = elems;
return false;
}
@ -1421,21 +1449,21 @@ JSObject::makeDenseArraySlow(JSContext *cx)
if (elems[i].isMagic(JS_ARRAY_HOLE))
continue;
if (!addDataProperty(cx, id, next, JSPROP_ENUMERATE)) {
this->shape_ = oldShape;
cx->free_(getElementsHeader());
elements = elems;
if (!obj->addDataProperty(cx, id, next, JSPROP_ENUMERATE)) {
obj->shape_ = oldShape;
cx->free_(obj->getElementsHeader());
obj->elements = elems;
return false;
}
initSlot(next, elems[i]);
obj->initSlot(next, elems[i]);
next++;
}
ObjectElements *oldheader = ObjectElements::fromElements(elems);
getElementsHeader()->length = oldheader->length;
obj->getElementsHeader()->length = oldheader->length;
cx->free_(oldheader);
return true;
@ -1706,7 +1734,7 @@ array_toString(JSContext *cx, unsigned argc, Value *vp)
JS_CHECK_RECURSION(cx, return false);
CallArgs args = CallArgsFromVp(argc, vp);
JSObject *obj = ToObject(cx, &args.thisv());
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -1780,7 +1808,7 @@ enum ShouldUpdateTypes
};
static bool
InitArrayElements(JSContext *cx, JSObject *obj, uint32_t start, uint32_t count, const Value *vector, ShouldUpdateTypes updateTypes)
InitArrayElements(JSContext *cx, HandleObject obj, uint32_t start, uint32_t count, const Value *vector, ShouldUpdateTypes updateTypes)
{
JS_ASSERT(count <= MAX_ARRAY_INDEX);
@ -1829,7 +1857,7 @@ InitArrayElements(JSContext *cx, JSObject *obj, uint32_t start, uint32_t count,
return true;
/* Finish out any remaining elements past the max array index. */
if (obj->isDenseArray() && !obj->makeDenseArraySlow(cx))
if (obj->isDenseArray() && !JSObject::makeDenseArraySlow(cx, obj))
return false;
JS_ASSERT(start == MAX_ARRAY_INDEX + 1);
@ -1908,7 +1936,7 @@ static JSBool
array_reverse(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSObject *obj = ToObject(cx, &args.thisv());
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -2212,7 +2240,7 @@ js::array_sort(JSContext *cx, unsigned argc, Value *vp)
fval.setNull();
}
JSObject *obj = ToObject(cx, &args.thisv());
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -2378,7 +2406,7 @@ js::array_sort(JSContext *cx, unsigned argc, Value *vp)
* Perl-inspired push, pop, shift, unshift, and splice methods.
*/
static bool
array_push_slowly(JSContext *cx, JSObject *obj, CallArgs &args)
array_push_slowly(JSContext *cx, HandleObject obj, CallArgs &args)
{
uint32_t length;
@ -2394,7 +2422,7 @@ array_push_slowly(JSContext *cx, JSObject *obj, CallArgs &args)
}
static bool
array_push1_dense(JSContext* cx, JSObject* obj, CallArgs &args)
array_push1_dense(JSContext* cx, HandleObject obj, CallArgs &args)
{
JS_ASSERT(args.length() == 1);
@ -2404,7 +2432,7 @@ array_push1_dense(JSContext* cx, JSObject* obj, CallArgs &args)
if (result == JSObject::ED_FAILED)
return false;
JS_ASSERT(result == JSObject::ED_SPARSE);
if (!obj->makeDenseArraySlow(cx))
if (!JSObject::makeDenseArraySlow(cx, obj))
return false;
return array_push_slowly(cx, obj, args);
}
@ -2450,7 +2478,7 @@ JSBool
js::array_push(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSObject *obj = ToObject(cx, &args.thisv());
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -2462,7 +2490,7 @@ js::array_push(JSContext *cx, unsigned argc, Value *vp)
}
static JSBool
array_pop_slowly(JSContext *cx, JSObject* obj, CallArgs &args)
array_pop_slowly(JSContext *cx, HandleObject obj, CallArgs &args)
{
uint32_t index;
if (!js_GetLengthProperty(cx, obj, &index))
@ -2488,7 +2516,7 @@ array_pop_slowly(JSContext *cx, JSObject* obj, CallArgs &args)
}
static JSBool
array_pop_dense(JSContext *cx, JSObject* obj, CallArgs &args)
array_pop_dense(JSContext *cx, HandleObject obj, CallArgs &args)
{
uint32_t index = obj->getArrayLength();
if (index == 0) {
@ -2518,7 +2546,7 @@ JSBool
js::array_pop(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSObject *obj = ToObject(cx, &args.thisv());
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
if (obj->isDenseArray())
@ -2547,7 +2575,7 @@ JSBool
js::array_shift(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSObject *obj = ToObject(cx, &args.thisv());
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return JS_FALSE;
@ -2599,7 +2627,7 @@ static JSBool
array_unshift(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSObject *obj = ToObject(cx, &args.thisv());
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -2721,7 +2749,7 @@ array_splice(JSContext *cx, unsigned argc, Value *vp)
CallArgs args = CallArgsFromVp(argc, vp);
/* Step 1. */
JSObject *obj = ToObject(cx, &args.thisv());
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -2852,7 +2880,7 @@ array_splice(JSContext *cx, unsigned argc, Value *vp)
return false;
if (res == JSObject::ED_SPARSE) {
if (!obj->makeDenseArraySlow(cx))
if (!JSObject::makeDenseArraySlow(cx, obj))
return false;
} else {
JS_ASSERT(res == JSObject::ED_OK);
@ -2944,11 +2972,11 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp)
Value *p = JS_ARGV(cx, vp) - 1;
/* Create a new Array object and root it using *vp. */
JSObject *aobj = ToObject(cx, &vp[1]);
RootedVarObject aobj(cx, ToObject(cx, &vp[1]));
if (!aobj)
return false;
JSObject *nobj;
RootedVarObject nobj(cx);
uint32_t length;
if (aobj->isDenseArray()) {
length = aobj->getArrayLength();
@ -3012,7 +3040,6 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp)
static JSBool
array_slice(JSContext *cx, unsigned argc, Value *vp)
{
JSObject *nobj;
uint32_t length, begin, end, slot;
JSBool hole;
@ -3057,6 +3084,8 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
if (begin > end)
begin = end;
RootedVarObject nobj(cx);
if (obj->isDenseArray() && end <= obj->getDenseArrayInitializedLength() &&
!js_PrototypeHasIndexedProperties(cx, obj)) {
nobj = NewDenseCopiedArray(cx, end - begin, obj->getDenseArrayElements() + begin);
@ -3336,7 +3365,7 @@ array_map(JSContext *cx, unsigned argc, Value *vp)
Value thisv = args.length() >= 2 ? args[1] : UndefinedValue();
/* Step 6. */
JSObject *arr = NewDenseAllocatedArray(cx, len);
RootedVarObject arr(cx, NewDenseAllocatedArray(cx, len));
if (!arr)
return false;
TypeObject *newtype = GetTypeCallerInitObject(cx, JSProto_Array);
@ -3412,7 +3441,7 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
Value thisv = args.length() >= 2 ? args[1] : UndefinedValue();
/* Step 6. */
JSObject *arr = NewDenseAllocatedArray(cx, 0);
RootedVarObject arr(cx, NewDenseAllocatedArray(cx, 0));
if (!arr)
return false;
TypeObject *newtype = GetTypeCallerInitObject(cx, JSProto_Array);
@ -3651,7 +3680,7 @@ JSBool
js_Array(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
TypeObject *type = GetTypeCallerInitObject(cx, JSProto_Array);
RootedVarTypeObject type(cx, GetTypeCallerInitObject(cx, JSProto_Array));
if (!type)
return JS_FALSE;
@ -3792,7 +3821,7 @@ NewArray(JSContext *cx, uint32_t length, JSObject *proto)
return obj;
}
Root<GlobalObject*> parentRoot(cx, &parent);
JS::Root<GlobalObject*> parentRoot(cx, &parent);
if (!proto && !FindProto(cx, &ArrayClass, parentRoot, &proto))
return NULL;
@ -3885,7 +3914,7 @@ NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *vp, JSObject *p
JSObject *
NewSlowEmptyArray(JSContext *cx)
{
JSObject *obj = NewBuiltinClassInstance(cx, &SlowArrayClass);
RootedVarObject obj(cx, NewBuiltinClassInstance(cx, &SlowArrayClass));
if (!obj || !AddLengthProperty(cx, obj))
return NULL;

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

@ -73,28 +73,6 @@ js_IdIsIndex(jsid id, uint32_t *indexp)
return js::StringIsArrayIndex(JSID_TO_ATOM(id), indexp);
}
/*
* Dense arrays are not native -- aobj->isNative() for a dense array aobj
* results in false, meaning aobj->map does not point to a js::Shape.
*
* But Array methods are called via aobj.sort(), e.g., and the interpreter and
* the trace recorder must consult the property cache in order to perform well.
* The cache works only for native objects.
*
* Therefore the interpreter (js_Interpret in JSOP_GETPROP and JSOP_CALLPROP)
* and js_GetPropertyHelper use this inline function to skip up one link in the
* prototype chain when obj is a dense array, in order to find a native object
* (to wit, Array.prototype) in which to probe for cached methods.
*
* Note that setting aobj.__proto__ for a dense array aobj turns aobj into a
* slow array, avoiding the neede to skip.
*
* Callers of js_GetProtoIfDenseArray must take care to use the original object
* (obj) for the |this| value of a getter, setter, or method call (bug 476447).
*/
inline JSObject *
js_GetProtoIfDenseArray(JSObject *obj);
extern JSObject *
js_InitArrayClass(JSContext *cx, JSObject *obj);

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

@ -156,14 +156,15 @@ js_InitBooleanClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = &obj->asGlobal();
RootedVar<GlobalObject*> global(cx, &obj->asGlobal());
JSObject *booleanProto = global->createBlankPrototype(cx, &BooleanClass);
RootedVarObject booleanProto (cx, global->createBlankPrototype(cx, &BooleanClass));
if (!booleanProto)
return NULL;
booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false));
JSFunction *ctor = global->createConstructor(cx, Boolean, CLASS_ATOM(cx, Boolean), 1);
RootedVarFunction ctor(cx);
ctor = global->createConstructor(cx, Boolean, CLASS_ATOM(cx, Boolean), 1);
if (!ctor)
return NULL;

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

@ -606,7 +606,7 @@ JSStructuredCloneWriter::write(const Value &v)
return false;
while (!counts.empty()) {
JSObject *obj = &objs.back().toObject();
RootedVarObject obj(context(), &objs.back().toObject());
// The objects in |obj| can live in other compartments.
AutoEnterCompartmentAndPushPrincipal ac;
@ -615,7 +615,7 @@ JSStructuredCloneWriter::write(const Value &v)
if (counts.back()) {
counts.back()--;
jsid id = ids.back();
RootedVarId id(context(), ids.back());
ids.popBack();
checkStack();
if (JSID_IS_STRING(id) || JSID_IS_INT(id)) {

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

@ -965,7 +965,7 @@ JSContext::JSContext(JSRuntime *rt)
#ifdef JSGC_ROOT_ANALYSIS
PodArrayZero(thingGCRooters);
#ifdef DEBUG
checkGCRooters = NULL;
skipGCRooters = NULL;
#endif
#endif
}

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

@ -742,9 +742,6 @@ struct JSArgumentFormatMap {
namespace js {
template <typename T> class Root;
class CheckRoot;
struct AutoResolving;
static inline bool
@ -1021,29 +1018,6 @@ struct JSContext : js::ContextFriendFields
JS_EndRequest. */
#endif
#ifdef JSGC_ROOT_ANALYSIS
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.
*/
js::Root<js::gc::Cell*> *thingGCRooters[js::THING_ROOT_COUNT];
#ifdef DEBUG
/*
* Stack allocated list of stack locations which hold non-relocatable
* GC heap pointers (where the target is rooted somewhere else) or integer
* values which may be confused for GC heap pointers. These are used to
* suppress false positives which occur when a rooting analysis treats the
* location as holding a relocatable pointer, but have no other effect on
* GC behavior.
*/
js::CheckRoot *checkGCRooters;
#endif
#endif /* JSGC_ROOT_ANALYSIS */
/* Stored here to avoid passing it around as a parameter. */
unsigned resolveFlags;

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

@ -326,7 +326,7 @@ JS_ALWAYS_INLINE bool
CallJSNativeConstructor(JSContext *cx, Native native, const CallArgs &args)
{
#ifdef DEBUG
JSObject &callee = args.callee();
RootedVarObject callee(cx, &args.callee());
#endif
JS_ASSERT(args.thisv().isMagic());
@ -351,8 +351,8 @@ CallJSNativeConstructor(JSContext *cx, Native native, const CallArgs &args)
JS_ASSERT_IF(native != FunctionProxyClass.construct &&
native != CallableObjectClass.construct &&
native != js::CallOrConstructBoundFunction &&
(!callee.isFunction() || callee.toFunction()->native() != js_Object),
!args.rval().isPrimitive() && callee != args.rval().toObject());
(!callee->isFunction() || callee->toFunction()->native() != js_Object),
!args.rval().isPrimitive() && callee != &args.rval().toObject());
return true;
}

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

@ -502,7 +502,8 @@ date_convert(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
JS_ASSERT(obj->isDate());
return DefaultValue(cx, obj, (hint == JSTYPE_VOID) ? JSTYPE_STRING : hint, vp);
return DefaultValue(cx, RootedVarObject(cx, obj),
(hint == JSTYPE_VOID) ? JSTYPE_STRING : hint, vp);
}
/*
@ -2664,14 +2665,15 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
/* Set the static LocalTZA. */
LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
GlobalObject *global = &obj->asGlobal();
RootedVar<GlobalObject*> global(cx, &obj->asGlobal());
JSObject *dateProto = global->createBlankPrototype(cx, &DateClass);
RootedVarObject dateProto(cx, global->createBlankPrototype(cx, &DateClass));
if (!dateProto)
return NULL;
SetDateToNaN(cx, dateProto);
JSFunction *ctor = global->createConstructor(cx, js_Date, CLASS_ATOM(cx, Date), MAXARGS);
RootedVarFunction ctor(cx);
ctor = global->createConstructor(cx, js_Date, CLASS_ATOM(cx, Date), MAXARGS);
if (!ctor)
return NULL;

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

@ -797,13 +797,15 @@ JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
}
JS_PUBLIC_API(JSBool)
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
JS_GetPropertyDesc(JSContext *cx, JSObject *obj_, JSScopeProperty *sprop,
JSPropertyDesc *pd)
{
assertSameCompartment(cx, obj);
assertSameCompartment(cx, obj_);
Shape *shape = (Shape *) sprop;
pd->id = IdToJsval(shape->propid());
RootedVarObject obj(cx, obj_);
JSBool wasThrowing = cx->isExceptionPending();
Value lastException = UndefinedValue();
if (wasThrowing)

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

@ -333,8 +333,8 @@ static void
SetExnPrivate(JSContext *cx, JSObject *exnObject, JSExnPrivate *priv);
static bool
InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
JSString *filename, unsigned lineno, JSErrorReport *report, int exnType)
InitExnPrivate(JSContext *cx, HandleObject exnObject, HandleString message,
HandleString filename, unsigned lineno, JSErrorReport *report, int exnType)
{
JS_ASSERT(exnObject->isError());
JS_ASSERT(!exnObject->getPrivate());
@ -502,7 +502,7 @@ exn_finalize(FreeOp *fop, JSObject *obj)
}
static JSBool
exn_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
exn_resolve(JSContext *cx, JSObject *obj_, jsid id, unsigned flags,
JSObject **objp)
{
JSExnPrivate *priv;
@ -513,6 +513,8 @@ exn_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
jsval v;
unsigned attrs;
RootedVarObject obj(cx, obj_);
*objp = NULL;
priv = GetExnPrivate(obj);
if (priv && JSID_IS_ATOM(id)) {
@ -779,12 +781,12 @@ Exception(JSContext *cx, unsigned argc, Value *vp)
}
JSObject *errProto = &protov.toObject();
JSObject *obj = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL);
RootedVarObject obj(cx, NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL));
if (!obj)
return false;
/* Set the 'message' property. */
JSString *message;
RootedVarString message(cx);
if (args.hasDefined(0)) {
message = ToString(cx, args[0]);
if (!message)
@ -800,7 +802,7 @@ Exception(JSContext *cx, unsigned argc, Value *vp)
++iter;
/* Set the 'fileName' property. */
JSString *filename;
RootedVarString filename(cx);
if (args.length() > 1) {
filename = ToString(cx, args[1]);
if (!filename)
@ -855,7 +857,7 @@ exn_toString(JSContext *cx, unsigned argc, Value *vp)
return false;
/* Step 4. */
JSString *name;
RootedVarString name(cx);
if (nameVal.isUndefined()) {
name = CLASS_ATOM(cx, Error);
} else {
@ -1008,19 +1010,19 @@ JS_STATIC_ASSERT(JSProto_Error + JSEXN_TYPEERR == JSProto_TypeError);
JS_STATIC_ASSERT(JSProto_Error + JSEXN_URIERR == JSProto_URIError);
static JSObject *
InitErrorClass(JSContext *cx, GlobalObject *global, int type, JSObject &proto)
InitErrorClass(JSContext *cx, Handle<GlobalObject*> global, int type, HandleObject proto)
{
JSProtoKey key = GetExceptionProtoKey(type);
JSAtom *name = cx->runtime->atomState.classAtoms[key];
JSObject *errorProto = global->createBlankPrototypeInheriting(cx, &ErrorClass, proto);
RootedVarAtom name(cx, cx->runtime->atomState.classAtoms[key]);
RootedVarObject errorProto(cx, global->createBlankPrototypeInheriting(cx, &ErrorClass, *proto));
if (!errorProto)
return NULL;
Value empty = StringValue(cx->runtime->emptyString);
jsid nameId = ATOM_TO_JSID(cx->runtime->atomState.nameAtom);
jsid messageId = ATOM_TO_JSID(cx->runtime->atomState.messageAtom);
jsid fileNameId = ATOM_TO_JSID(cx->runtime->atomState.fileNameAtom);
jsid lineNumberId = ATOM_TO_JSID(cx->runtime->atomState.lineNumberAtom);
RootedVarValue empty(cx, StringValue(cx->runtime->emptyString));
RootedVarId nameId(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom));
RootedVarId messageId(cx, ATOM_TO_JSID(cx->runtime->atomState.messageAtom));
RootedVarId fileNameId(cx, ATOM_TO_JSID(cx->runtime->atomState.fileNameAtom));
RootedVarId lineNumberId(cx, ATOM_TO_JSID(cx->runtime->atomState.lineNumberAtom));
if (!DefineNativeProperty(cx, errorProto, nameId, StringValue(name),
JS_PropertyStub, JS_StrictPropertyStub, 0, 0, 0) ||
!DefineNativeProperty(cx, errorProto, messageId, empty,
@ -1034,8 +1036,9 @@ InitErrorClass(JSContext *cx, GlobalObject *global, int type, JSObject &proto)
}
/* Create the corresponding constructor. */
JSFunction *ctor = global->createConstructor(cx, Exception, name, 1,
JSFunction::ExtendedFinalizeKind);
RootedVarFunction ctor(cx);
ctor = global->createConstructor(cx, Exception, name, 1,
JSFunction::ExtendedFinalizeKind);
if (!ctor)
return NULL;
ctor->setExtendedSlot(0, Int32Value(int32_t(type)));
@ -1057,14 +1060,15 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
JS_ASSERT(obj->isGlobal());
JS_ASSERT(obj->isNative());
GlobalObject *global = &obj->asGlobal();
RootedVar<GlobalObject*> global(cx, &obj->asGlobal());
JSObject *objectProto = global->getOrCreateObjectPrototype(cx);
RootedVarObject objectProto(cx, global->getOrCreateObjectPrototype(cx));
if (!objectProto)
return NULL;
/* Initialize the base Error class first. */
JSObject *errorProto = InitErrorClass(cx, global, JSEXN_ERR, *objectProto);
RootedVarObject errorProto(cx);
errorProto = InitErrorClass(cx, global, JSEXN_ERR, objectProto);
if (!errorProto)
return NULL;
@ -1074,7 +1078,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
/* Define all remaining *Error constructors. */
for (int i = JSEXN_ERR + 1; i < JSEXN_LIMIT; i++) {
if (!InitErrorClass(cx, global, i, *errorProto))
if (!InitErrorClass(cx, global, i, errorProto))
return NULL;
}
@ -1127,6 +1131,24 @@ static struct exnname { char *name; char *exception; } errortoexnname[] = {
};
#endif /* DEBUG */
struct AutoSetGeneratingError
{
JSContext *cx;
AutoSetGeneratingError(JSContext *cx)
: cx(cx)
{
JS_ASSERT(!cx->generatingError);
cx->generatingError = true;
}
~AutoSetGeneratingError()
{
JS_ASSERT(cx->generatingError);
cx->generatingError = false;
}
};
JSBool
js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
JSErrorCallback callback, void *userRef)
@ -1135,8 +1157,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
const JSErrorFormatString *errorString;
JSExnType exn;
jsval tv[4];
JSObject *errProto, *errObject;
JSString *messageStr, *filenameStr;
JSObject *errProto;
/*
* Tell our caller to report immediately if this report is just a warning.
@ -1186,15 +1207,18 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
return false;
tv[0] = OBJECT_TO_JSVAL(errProto);
if (!(errObject = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL)))
RootedVarObject errObject(cx, NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL));
if (!errObject)
return false;
tv[1] = OBJECT_TO_JSVAL(errObject);
if (!(messageStr = JS_NewStringCopyZ(cx, message)))
RootedVarString messageStr(cx, JS_NewStringCopyZ(cx, message));
if (!messageStr)
return false;
tv[2] = STRING_TO_JSVAL(messageStr);
if (!(filenameStr = JS_NewStringCopyZ(cx, reportp->filename)))
RootedVarString filenameStr(cx, JS_NewStringCopyZ(cx, reportp->filename));
if (!filenameStr)
return false;
tv[3] = STRING_TO_JSVAL(filenameStr);
@ -1235,7 +1259,6 @@ IsDuckTypedErrorObject(JSContext *cx, JSObject *exnObject, const char **filename
JSBool
js_ReportUncaughtException(JSContext *cx)
{
jsval exn;
JSObject *exnObject;
jsval roots[6];
JSErrorReport *reportp, report;
@ -1244,7 +1267,8 @@ js_ReportUncaughtException(JSContext *cx)
if (!JS_IsExceptionPending(cx))
return true;
if (!JS_GetPendingException(cx, &exn))
RootedVarValue exn(cx);
if (!JS_GetPendingException(cx, exn.address()))
return false;
PodArrayZero(roots);

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

@ -189,17 +189,6 @@ JS_END_EXTERN_C
namespace js {
struct ContextFriendFields {
JSRuntime *const runtime;
ContextFriendFields(JSRuntime *rt)
: runtime(rt) { }
static const ContextFriendFields *get(const JSContext *cx) {
return reinterpret_cast<const ContextFriendFields *>(cx);
}
};
struct RuntimeFriendFields {
/*
* If non-zero, we were been asked to call the operation callback as soon

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

@ -244,7 +244,7 @@ fun_enumerate(JSContext *cx, JSObject *obj)
}
static JSObject *
ResolveInterpretedFunctionPrototype(JSContext *cx, JSObject *obj)
ResolveInterpretedFunctionPrototype(JSContext *cx, HandleObject obj)
{
#ifdef DEBUG
JSFunction *fun = obj->toFunction();
@ -267,7 +267,7 @@ ResolveInterpretedFunctionPrototype(JSContext *cx, JSObject *obj)
JSObject *objProto = obj->global().getOrCreateObjectPrototype(cx);
if (!objProto)
return NULL;
JSObject *proto = NewObjectWithGivenProto(cx, &ObjectClass, objProto, NULL);
RootedVarObject proto(cx, NewObjectWithGivenProto(cx, &ObjectClass, objProto, NULL));
if (!proto || !proto->setSingletonType(cx))
return NULL;
@ -1078,7 +1078,7 @@ Function(JSContext *cx, unsigned argc, Value *vp)
return OnBadFormal(cx, tt);
/* Check for a duplicate parameter name. */
PropertyName *name = ts.currentToken().name();
RootedVar<PropertyName*> name(cx, ts.currentToken().name());
if (bindings.hasBinding(cx, name)) {
JSAutoByteString bytes;
if (!js_AtomToPrintableString(cx, name, &bytes))
@ -1150,7 +1150,7 @@ IsBuiltinFunctionConstructor(JSFunction *fun)
}
const Shape *
LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj)
LookupInterpretedFunctionPrototype(JSContext *cx, RootedVarObject funobj)
{
#ifdef DEBUG
JSFunction *fun = funobj->toFunction();
@ -1160,10 +1160,11 @@ LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj)
#endif
jsid id = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
const Shape *shape = funobj->nativeLookup(cx, id);
RootedVar<const Shape*> shape(cx, funobj->nativeLookup(cx, id));
if (!shape) {
if (!ResolveInterpretedFunctionPrototype(cx, funobj))
return NULL;
id = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
shape = funobj->nativeLookup(cx, id);
}
JS_ASSERT(!shape->configurable());
@ -1176,12 +1177,14 @@ LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj)
JSFunction *
js_NewFunction(JSContext *cx, JSObject *funobj, Native native, unsigned nargs,
unsigned flags, HandleObject parent, JSAtom *atom, js::gc::AllocKind kind)
unsigned flags, HandleObject parent, JSAtom *atom_, js::gc::AllocKind kind)
{
JS_ASSERT(kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
JS_ASSERT(sizeof(JSFunction) <= gc::Arena::thingSize(JSFunction::FinalizeKind));
JS_ASSERT(sizeof(FunctionExtended) <= gc::Arena::thingSize(JSFunction::ExtendedFinalizeKind));
RootedVarAtom atom(cx, atom_);
JSFunction *fun;
if (funobj) {
@ -1218,8 +1221,8 @@ js_NewFunction(JSContext *cx, JSObject *funobj, Native native, unsigned nargs,
}
JSFunction * JS_FASTCALL
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
JSObject *proto, gc::AllocKind kind)
js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
HandleObject proto, gc::AllocKind kind)
{
JS_ASSERT(parent);
JS_ASSERT(proto);

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

@ -245,7 +245,8 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, unsigned nargs,
js::gc::AllocKind kind = JSFunction::FinalizeKind);
extern JSFunction * JS_FASTCALL
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, JSObject *proto,
js_CloneFunctionObject(JSContext *cx, js::HandleFunction fun,
js::HandleObject parent, js::HandleObject proto,
js::gc::AllocKind kind = JSFunction::FinalizeKind);
extern JSFunction *

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

@ -145,13 +145,13 @@ IsNativeFunction(const js::Value &v, JSNative native)
* TODO: a per-thread shape-based cache would be faster and simpler.
*/
static JS_ALWAYS_INLINE bool
ClassMethodIsNative(JSContext *cx, JSObject *obj, Class *clasp, jsid methodid, JSNative native)
ClassMethodIsNative(JSContext *cx, HandleObject obj, Class *clasp, HandleId methodid, JSNative native)
{
JS_ASSERT(obj->getClass() == clasp);
Value v;
if (!HasDataProperty(cx, obj, methodid, &v)) {
JSObject *proto = obj->getProto();
RootedVarObject proto(cx, obj->getProto());
if (!proto || proto->getClass() != clasp || !HasDataProperty(cx, proto, methodid, &v))
return false;
}
@ -205,21 +205,6 @@ Function(JSContext *cx, unsigned argc, Value *vp);
extern bool
IsBuiltinFunctionConstructor(JSFunction *fun);
/*
* Preconditions: funobj->isInterpreted() && !funobj->isFunctionPrototype() &&
* !funobj->isBoundFunction(). This is sufficient to establish that funobj has
* a non-configurable non-method .prototype data property, thought it might not
* have been resolved yet, and its value could be anything.
*
* Return the shape of the .prototype property of funobj, resolving it if
* needed. On error, return NULL.
*
* This is not safe to call on trace because it defines properties, which can
* trigger lookups that could reenter.
*/
const Shape *
LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj);
static inline JSObject *
SkipScopeParent(JSObject *parent)
{
@ -231,11 +216,11 @@ SkipScopeParent(JSObject *parent)
}
inline JSFunction *
CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
gc::AllocKind kind = JSFunction::FinalizeKind)
{
JS_ASSERT(parent);
JSObject *proto = parent->global().getOrCreateFunctionPrototype(cx);
RootedVarObject proto(cx, parent->global().getOrCreateFunctionPrototype(cx));
if (!proto)
return NULL;
@ -243,7 +228,7 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
}
inline JSFunction *
CloneFunctionObjectIfNotSingleton(JSContext *cx, JSFunction *fun, JSObject *parent)
CloneFunctionObjectIfNotSingleton(JSContext *cx, HandleFunction fun, HandleObject parent)
{
/*
* For attempts to clone functions at a function definition opcode,
@ -263,7 +248,7 @@ CloneFunctionObjectIfNotSingleton(JSContext *cx, JSFunction *fun, JSObject *pare
}
inline JSFunction *
CloneFunctionObject(JSContext *cx, JSFunction *fun)
CloneFunctionObject(JSContext *cx, HandleFunction fun)
{
/*
* Variant which makes an exact clone of fun, preserving parent and proto.
@ -277,7 +262,9 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun)
if (fun->hasSingletonType())
return fun;
return js_CloneFunctionObject(cx, fun, fun->environment(), fun->getProto(),
return js_CloneFunctionObject(cx, fun,
RootedVarObject(cx, fun->environment()),
RootedVarObject(cx, fun->getProto()),
JSFunction::ExtendedFinalizeKind);
}

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

@ -3945,25 +3945,27 @@ CheckStackRoot(JSTracer *trc, uintptr_t *w)
VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(w));
#endif
ConservativeGCTest test = MarkIfGCThingWord(trc, *w, DONT_MARK_THING);
ConservativeGCTest test = MarkIfGCThingWord(trc, *w);
if (test == CGCT_VALID) {
JSContext *iter = NULL;
bool matched = false;
JSRuntime *rt = trc->runtime;
for (unsigned i = 0; i < THING_ROOT_COUNT; i++) {
Root<Cell*> *rooter = rt->thingGCRooters[i];
while (rooter) {
if (rooter->address() == (Cell **) w)
matched = true;
rooter = rooter->previous();
for (ContextIter cx(rt); !cx.done(); cx.next()) {
for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) {
Root<void*> *rooter = cx->thingGCRooters[i];
while (rooter) {
if (rooter->address() == static_cast<void*>(w))
matched = true;
rooter = rooter->previous();
}
}
SkipRoot *skip = cx->skipGCRooters;
while (skip) {
if (skip->contains(reinterpret_cast<uint8_t*>(w), sizeof(w)))
matched = true;
skip = skip->previous();
}
}
CheckRoot *check = rt->checkGCRooters;
while (check) {
if (check->contains(static_cast<uint8_t*>(w), sizeof(w)))
matched = true;
check = check->previous();
}
if (!matched) {
/*
@ -4001,17 +4003,17 @@ CheckStackRoots(JSContext *cx)
JS_ASSERT(ctd->hasStackToScan());
uintptr_t *stackMin, *stackEnd;
#if JS_STACK_GROWTH_DIRECTION > 0
stackMin = td->nativeStackBase;
stackEnd = ctd->nativeStackTop;
stackMin = rt->nativeStackBase;
stackEnd = cgcd->nativeStackTop;
#else
stackMin = ctd->nativeStackTop + 1;
stackEnd = td->nativeStackBase;
stackMin = cgcd->nativeStackTop + 1;
stackEnd = reinterpret_cast<uintptr_t *>(rt->nativeStackBase);
#endif
JS_ASSERT(stackMin <= stackEnd);
CheckStackRootsRange(&checker, stackMin, stackEnd);
CheckStackRootsRange(&checker, ctd->registerSnapshot.words,
ArrayEnd(ctd->registerSnapshot.words));
CheckStackRootsRange(&checker, cgcd->registerSnapshot.words,
ArrayEnd(cgcd->registerSnapshot.words));
}
#endif /* DEBUG && JSGC_ROOT_ANALYSIS && !JS_THREADSAFE */

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

@ -1697,7 +1697,7 @@ public:
};
static void
CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun);
CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, JSFunction *fun);
bool
TypeSet::isOwnProperty(JSContext *cx, TypeObject *object, bool configurable)
@ -1710,7 +1710,8 @@ TypeSet::isOwnProperty(JSContext *cx, TypeObject *object, bool configurable)
*/
if (object->flags & OBJECT_FLAG_NEW_SCRIPT_REGENERATE) {
if (object->newScript) {
CheckNewScriptProperties(cx, object, object->newScript->fun);
CheckNewScriptProperties(cx, RootedVarTypeObject(cx, object),
object->newScript->fun);
} else {
JS_ASSERT(object->flags & OBJECT_FLAG_NEW_SCRIPT_CLEARED);
object->flags &= ~OBJECT_FLAG_NEW_SCRIPT_REGENERATE;
@ -4382,7 +4383,7 @@ AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun, JSO
pc = script->code + uses->offset;
op = JSOp(*pc);
JSObject *obj = *pbaseobj;
RootedVarObject obj(cx, *pbaseobj);
if (op == JSOP_SETPROP && uses->u.which == 1) {
/*
@ -4532,13 +4533,14 @@ AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun, JSO
* newScript on the type after they were cleared by a GC.
*/
static void
CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, JSFunction *fun)
{
if (type->unknownProperties() || fun->script()->isInnerFunction)
return;
/* Strawman object to add properties to and watch for duplicates. */
JSObject *baseobj = NewBuiltinClassInstance(cx, &ObjectClass, gc::FINALIZE_OBJECT16);
RootedVarObject baseobj(cx);
baseobj = NewBuiltinClassInstance(cx, &ObjectClass, gc::FINALIZE_OBJECT16);
if (!baseobj) {
if (type->newScript)
type->clearNewScript(cx);
@ -4546,7 +4548,7 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
}
Vector<TypeNewScript::Initializer> initializerList(cx);
AnalyzeNewScriptProperties(cx, type, fun, &baseobj, &initializerList);
AnalyzeNewScriptProperties(cx, type, fun, baseobj.address(), &initializerList);
if (!baseobj || baseobj->slotSpan() == 0 || !!(type->flags & OBJECT_FLAG_NEW_SCRIPT_CLEARED)) {
if (type->newScript)
type->clearNewScript(cx);
@ -5365,10 +5367,12 @@ JSScript::makeAnalysis(JSContext *cx)
if (!types->analysis)
return false;
RootedVar<JSScript*> self(cx, this);
types->analysis->analyzeBytecode(cx);
if (types->analysis->OOM()) {
types->analysis = NULL;
if (self->types->analysis->OOM()) {
self->types->analysis = NULL;
return false;
}
@ -5654,12 +5658,12 @@ JSObject::getNewType(JSContext *cx, JSFunction *fun)
bool markUnknown = self->lastProperty()->hasObjectFlag(BaseShape::NEW_TYPE_UNKNOWN);
TypeObject *type = cx->compartment->types.newTypeObject(cx, NULL,
JSProto_Object, self, markUnknown);
RootedVarTypeObject type(cx);
type = cx->compartment->types.newTypeObject(cx, NULL, JSProto_Object, self, markUnknown);
if (!type)
return NULL;
if (!table.relookupOrAdd(p, self, type))
if (!table.relookupOrAdd(p, self, type.raw()))
return NULL;
if (!cx->typeInferenceEnabled())

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

@ -1427,11 +1427,11 @@ inline bool
JSScript::ensureRanAnalysis(JSContext *cx, JSObject *scope)
{
JSScript *self = this;
JS::SkipRoot root(cx, &self);
if (!self->ensureHasTypes(cx))
return false;
if (!self->types->hasScope()) {
js::CheckRoot root(cx, &self);
js::RootObject objRoot(cx, &scope);
if (!js::types::TypeScript::SetScope(cx, self, scope))
return false;

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

@ -208,7 +208,8 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
*
* create() leaves the clone's enclosingScope unset. We set it below.
*/
ClonedBlockObject *innermostNewChild = ClonedBlockObject::create(cx, *sharedBlock, fp);
RootedVar<ClonedBlockObject *> innermostNewChild(cx);
innermostNewChild = ClonedBlockObject::create(cx, *sharedBlock, fp);
if (!innermostNewChild)
return NULL;
@ -216,7 +217,7 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
* Clone our way towards outer scopes until we reach the innermost
* enclosing function, or the innermost block we've already cloned.
*/
ClonedBlockObject *newChild = innermostNewChild;
RootedVar<ClonedBlockObject *> newChild(cx, innermostNewChild);
for (;;) {
JS_ASSERT(newChild->getProto() == sharedBlock);
sharedBlock = sharedBlock->enclosingBlock();
@ -226,18 +227,17 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
break;
/* As in the call above, we don't know the real parent yet. */
ClonedBlockObject *clone = ClonedBlockObject::create(cx, *sharedBlock, fp);
RootedVar<ClonedBlockObject *> clone(cx, ClonedBlockObject::create(cx, *sharedBlock, fp));
if (!clone)
return NULL;
if (!newChild->setEnclosingScope(cx, *clone))
if (!newChild->setEnclosingScope(cx, clone))
return NULL;
newChild = clone;
}
if (!newChild->setEnclosingScope(cx, fp->scopeChain()))
if (!newChild->setEnclosingScope(cx, RootedVarObject(cx, &fp->scopeChain())))
return NULL;
/*
* If we found a limit block belonging to this frame, then we should have
* found it in blockChain.
@ -365,7 +365,7 @@ Class js_NoSuchMethodClass = {
* parameters.
*/
bool
js::OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp)
js::OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval, Value *vp)
{
jsid id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom);
AutoValueRooter tvr(cx);
@ -379,13 +379,13 @@ js::OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp)
#if JS_HAS_XML_SUPPORT
/* Extract the function name from function::name qname. */
if (idval.isObject()) {
obj = &idval.toObject();
JSObject *obj = &idval.toObject();
if (js_GetLocalNameFromFunctionQName(obj, &id, cx))
idval = IdToValue(id);
}
#endif
obj = NewObjectWithClassProto(cx, &js_NoSuchMethodClass, NULL, NULL);
JSObject *obj = NewObjectWithClassProto(cx, &js_NoSuchMethodClass, NULL, NULL);
if (!obj)
return false;
@ -644,7 +644,7 @@ js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const V
{
JS_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG);
Root<JSScript*> scriptRoot(cx, &script);
JS::Root<JSScript*> scriptRoot(cx, &script);
if (script->isEmpty()) {
if (result)
@ -924,7 +924,7 @@ EnterWith(JSContext *cx, int stackIndex)
JS_ASSERT(stackIndex < 0);
JS_ASSERT(fp->base() <= sp + stackIndex);
JSObject *obj;
RootedVarObject obj(cx);
if (sp[-1].isObject()) {
obj = &sp[-1].toObject();
} else {
@ -934,11 +934,11 @@ EnterWith(JSContext *cx, int stackIndex)
sp[-1].setObject(*obj);
}
JSObject *parent = GetScopeChain(cx, fp);
RootedVarObject parent(cx, GetScopeChain(cx, fp));
if (!parent)
return JS_FALSE;
JSObject *withobj = WithObject::create(cx, fp, *obj, *parent,
JSObject *withobj = WithObject::create(cx, fp, obj, parent,
sp + stackIndex - fp->base());
if (!withobj)
return JS_FALSE;
@ -1222,10 +1222,10 @@ inline InterpreterFrames::~InterpreterFrames()
context->runtime->interpreterFrames = older;
}
#if defined(DEBUG) && !defined(JS_THREADSAFE)
#if defined(DEBUG) && !defined(JS_THREADSAFE) && !defined(JSGC_ROOT_ANALYSIS)
void
js::AssertValidPropertyCacheHit(JSContext *cx,
JSObject *start, JSObject *found,
JSObject *start_, JSObject *found,
PropertyCacheEntry *entry)
{
jsbytecode *pc;
@ -1234,7 +1234,8 @@ js::AssertValidPropertyCacheHit(JSContext *cx,
uint64_t sample = cx->runtime->gcNumber;
PropertyCacheEntry savedEntry = *entry;
PropertyName *name = GetNameFromBytecode(cx, pc, JSOp(*pc), js_CodeSpec[*pc]);
RootedVarPropertyName name(cx, GetNameFromBytecode(cx, pc, JSOp(*pc), js_CodeSpec[*pc]));
RootedVarObject start(cx, start_);
JSObject *obj, *pobj;
JSProperty *prop;
@ -1294,7 +1295,7 @@ IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval)
return true;
}
}
if (!js_IteratorMore(cx, iterobj, rval))
if (!js_IteratorMore(cx, RootedVarObject(cx, iterobj), rval))
return false;
*cond = rval->isTrue();
return true;
@ -1544,11 +1545,25 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
/* Copy in hot values that change infrequently. */
JSRuntime *const rt = cx->runtime;
JSScript *script;
RootedVar<JSScript*> script(cx);
SET_SCRIPT(regs.fp()->script());
Value *argv = regs.fp()->maybeFormalArgs();
CHECK_INTERRUPT_HANDLER();
/*
* Pool of rooters for use in this interpreter frame. References to these
* are used for local variables within interpreter cases. This avoids
* creating new rooters each time an interpreter case is entered, and also
* correctness pitfalls due to incorrect compilation of destructor calls
* around computed gotos.
*/
RootedVarValue rootValue0(cx), rootValue1(cx);
RootedVarString rootString0(cx), rootString1(cx);
RootedVarObject rootObject0(cx), rootObject1(cx);
RootedVarFunction rootFunction0(cx);
RootedVarTypeObject rootType0(cx);
RootedVarPropertyName rootName0(cx);
if (rt->profilingScripts)
ENABLE_INTERRUPTS();
@ -2481,11 +2496,15 @@ END_CASE(JSOP_POS)
BEGIN_CASE(JSOP_DELNAME)
{
PropertyName *name;
RootedVarPropertyName &name = rootName0;
LOAD_NAME(0, name);
RootedVarObject &scopeObj = rootObject0;
scopeObj = cx->stack.currentScriptedScopeChain();
JSObject *obj, *obj2;
JSProperty *prop;
if (!FindProperty(cx, name, cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
if (!FindProperty(cx, name, scopeObj, &obj, &obj2, &prop))
goto error;
/* Strict mode code should never contain JSOP_DELNAME opcodes. */
@ -2724,10 +2743,10 @@ BEGIN_CASE(JSOP_FUNCALL)
bool construct = (*regs.pc == JSOP_NEW);
JSFunction *fun;
RootedVarFunction &fun = rootFunction0;
/* Don't bother trying to fast-path calls to scripted non-constructors. */
if (!IsFunctionObject(args.calleev(), &fun) || !fun->isInterpretedConstructor()) {
if (!IsFunctionObject(args.calleev(), fun.address()) || !fun->isInterpretedConstructor()) {
if (construct) {
if (!InvokeConstructorKernel(cx, args))
goto error;
@ -2821,12 +2840,15 @@ END_CASE(JSOP_SETCALL)
BEGIN_CASE(JSOP_IMPLICITTHIS)
{
PropertyName *name;
RootedVarPropertyName &name = rootName0;
LOAD_NAME(0, name);
RootedVarObject &scopeObj = rootObject0;
scopeObj = cx->stack.currentScriptedScopeChain();
JSObject *obj, *obj2;
JSProperty *prop;
if (!FindPropertyHelper(cx, name, false, cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
if (!FindPropertyHelper(cx, name, false, scopeObj, &obj, &obj2, &prop))
goto error;
Value v;
@ -2841,8 +2863,9 @@ BEGIN_CASE(JSOP_CALLGNAME)
BEGIN_CASE(JSOP_NAME)
BEGIN_CASE(JSOP_CALLNAME)
{
Value rval;
if (!NameOperation(cx, regs.pc, &rval))
RootedVarValue &rval = rootValue0;
if (!NameOperation(cx, regs.pc, rval.address()))
goto error;
PUSH_COPY(rval);
@ -3115,7 +3138,8 @@ BEGIN_CASE(JSOP_DEFVAR)
attrs |= JSPROP_READONLY;
/* Step 8b. */
JSObject &obj = regs.fp()->varObj();
RootedVarObject &obj = rootObject0;
obj = &regs.fp()->varObj();
if (!DefVarOrConstOperation(cx, obj, dn, attrs))
goto error;
@ -3130,10 +3154,11 @@ BEGIN_CASE(JSOP_DEFFUN)
* a compound statement (not at the top statement level of global code, or
* at the top level of a function body).
*/
JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
RootedVarFunction &fun = rootFunction0;
fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
JSObject *obj = fun;
JSObject *obj2;
RootedVarObject &obj2 = rootObject0;
if (fun->isNullClosure()) {
/*
* Even a null closure needs a parent for principals finding.
@ -3238,12 +3263,13 @@ END_CASE(JSOP_DEFFUN)
BEGIN_CASE(JSOP_LAMBDA)
{
/* Load the specified function object literal. */
JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
RootedVarFunction &fun = rootFunction0;
fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
JSObject *obj = fun;
/* do-while(0) so we can break instead of using a goto. */
do {
JSObject *parent;
RootedVarObject &parent = rootObject0;
if (fun->isNullClosure()) {
parent = &regs.fp()->scopeChain();
} else {
@ -3405,9 +3431,11 @@ END_CASE(JSOP_NEWARRAY)
BEGIN_CASE(JSOP_NEWOBJECT)
{
JSObject *baseobj = script->getObject(GET_UINT32_INDEX(regs.pc));
RootedVarObject &baseobj = rootObject0;
baseobj = script->getObject(GET_UINT32_INDEX(regs.pc));
JSObject *obj = CopyInitializerObject(cx, baseobj);
RootedVarObject &obj = rootObject1;
obj = CopyInitializerObject(cx, baseobj);
if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj))
goto error;
@ -3431,7 +3459,8 @@ BEGIN_CASE(JSOP_INITPROP)
Value rval = regs.sp[-1];
/* Load the object being initialized into lval/obj. */
JSObject *obj = &regs.sp[-2].toObject();
RootedVarObject &obj = rootObject0;
obj = &regs.sp[-2].toObject();
JS_ASSERT(obj->isObject());
JSAtom *atom;

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

@ -322,7 +322,7 @@ extern void
UnwindForUncatchableException(JSContext *cx, const FrameRegs &regs);
extern bool
OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp);
OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval, Value *vp);
extern bool
IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth);

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

@ -171,7 +171,7 @@ NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj, const Shape *shape, unsi
return true;
}
#if defined(DEBUG) && !defined(JS_THREADSAFE)
#if defined(DEBUG) && !defined(JS_THREADSAFE) && !defined(JSGC_ROOT_ANALYSIS)
extern void
AssertValidPropertyCacheHit(JSContext *cx, JSObject *start, JSObject *found,
PropertyCacheEntry *entry);
@ -183,7 +183,7 @@ AssertValidPropertyCacheHit(JSContext *cx, JSObject *start, JSObject *found,
#endif
inline bool
GetPropertyGenericMaybeCallXML(JSContext *cx, JSOp op, JSObject *obj, jsid id, Value *vp)
GetPropertyGenericMaybeCallXML(JSContext *cx, JSOp op, HandleObject obj, jsid id, Value *vp)
{
/*
* Various XML properties behave differently when accessed in a
@ -255,13 +255,15 @@ GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp
return true;
}
RootObject objRoot(cx, &obj);
jsid id = ATOM_TO_JSID(name);
if (obj->getOps()->getProperty) {
if (!GetPropertyGenericMaybeCallXML(cx, op, obj, id, vp))
if (!GetPropertyGenericMaybeCallXML(cx, op, objRoot, id, vp))
return false;
} else {
if (!GetPropertyHelper(cx, obj, id, JSGET_CACHE_RESULT, vp))
if (!GetPropertyHelper(cx, objRoot, id, JSGET_CACHE_RESULT, vp))
return false;
}
@ -270,7 +272,7 @@ GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp
JS_UNLIKELY(vp->isPrimitive()) &&
lval.isObject())
{
if (!OnUnknownMethod(cx, obj, IdToValue(id), vp))
if (!OnUnknownMethod(cx, objRoot, IdToValue(id), vp))
return false;
}
#endif
@ -308,9 +310,9 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Val
((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape)) {
#ifdef DEBUG
if (entry->isOwnPropertyHit()) {
JS_ASSERT(obj->nativeContains(cx, *shape));
JS_ASSERT(obj->nativeLookupNoAllocation(cx, shape->propid()) == shape);
} else {
JS_ASSERT(obj2->nativeContains(cx, *shape));
JS_ASSERT(obj2->nativeLookupNoAllocation(cx, shape->propid()) == shape);
JS_ASSERT(entry->isPrototypePropertyHit());
JS_ASSERT(entry->kshape != entry->pshape);
JS_ASSERT(!shape->hasSlot());
@ -333,19 +335,21 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Val
}
bool strict = cx->stack.currentScript()->strictModeCode;
Value rref = rval;
RootedVarValue rref(cx, rval);
JSOp op = JSOp(*pc);
RootObject objRoot(cx, &obj);
jsid id = ATOM_TO_JSID(name);
if (JS_LIKELY(!obj->getOps()->setProperty)) {
unsigned defineHow = (op == JSOP_SETNAME)
? DNP_CACHE_RESULT | DNP_UNQUALIFIED
: DNP_CACHE_RESULT;
if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rref, strict))
if (!js_SetPropertyHelper(cx, objRoot, id, defineHow, rref.address(), strict))
return false;
} else {
if (!obj->setGeneric(cx, id, &rref, strict))
if (!obj->setGeneric(cx, id, rref.address(), strict))
return false;
}
@ -382,8 +386,11 @@ NameOperation(JSContext *cx, jsbytecode *pc, Value *vp)
jsid id = ATOM_TO_JSID(name);
RootPropertyName nameRoot(cx, &name);
RootObject objRoot(cx, &obj);
JSProperty *prop;
if (!FindPropertyHelper(cx, name, true, obj, &obj, &obj2, &prop))
if (!FindPropertyHelper(cx, nameRoot, true, objRoot, &obj, &obj2, &prop))
return false;
if (!prop) {
/* Kludge to allow (typeof foo == "undefined") tests. */
@ -415,19 +422,19 @@ NameOperation(JSContext *cx, jsbytecode *pc, Value *vp)
}
inline bool
DefVarOrConstOperation(JSContext *cx, JSObject &varobj, PropertyName *dn, unsigned attrs)
DefVarOrConstOperation(JSContext *cx, HandleObject varobj, PropertyName *dn, unsigned attrs)
{
JS_ASSERT(varobj.isVarObj());
JS_ASSERT(!varobj.getOps()->defineProperty);
JS_ASSERT(varobj->isVarObj());
JS_ASSERT(!varobj->getOps()->defineProperty);
JSProperty *prop;
JSObject *obj2;
if (!varobj.lookupProperty(cx, dn, &obj2, &prop))
if (!varobj->lookupProperty(cx, dn, &obj2, &prop))
return false;
/* Steps 8c, 8d. */
if (!prop || (obj2 != &varobj && varobj.isGlobal())) {
if (!DefineNativeProperty(cx, &varobj, dn, UndefinedValue(),
if (!prop || (obj2 != varobj && varobj->isGlobal())) {
if (!DefineNativeProperty(cx, varobj, dn, UndefinedValue(),
JS_PropertyStub, JS_StrictPropertyStub, attrs, 0, 0))
{
return false;
@ -438,7 +445,7 @@ DefVarOrConstOperation(JSContext *cx, JSObject &varobj, PropertyName *dn, unsign
* see a redeclaration that's |const|, we consider it a conflict.
*/
unsigned oldAttrs;
if (!varobj.getPropertyAttributes(cx, dn, &oldAttrs))
if (!varobj->getPropertyAttributes(cx, dn, &oldAttrs))
return false;
if (attrs & JSPROP_READONLY) {
JSAutoByteString bytes;
@ -478,7 +485,7 @@ ScriptPrologue(JSContext *cx, StackFrame *fp, bool newType)
JS_ASSERT_IF(fp->isNonEvalFunctionFrame() && fp->fun()->isHeavyweight(), fp->hasCallObj());
if (fp->isConstructing()) {
JSObject *obj = js_CreateThisForFunction(cx, &fp->callee(), newType);
JSObject *obj = js_CreateThisForFunction(cx, RootedVarObject(cx, &fp->callee()), newType);
if (!obj)
return false;
fp->functionThis().setObject(*obj);
@ -532,11 +539,8 @@ InterpreterFrames::enableInterruptsIfRunning(JSScript *script)
static JS_ALWAYS_INLINE bool
AddOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
{
Value lval = lhs;
Value rval = rhs;
if (lval.isInt32() && rval.isInt32()) {
int32_t l = lval.toInt32(), r = rval.toInt32();
if (lhs.isInt32() && rhs.isInt32()) {
int32_t l = lhs.toInt32(), r = rhs.toInt32();
int32_t sum = l + r;
if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000))) {
res->setDouble(double(l) + double(r));
@ -546,13 +550,18 @@ AddOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
}
} else
#if JS_HAS_XML_SUPPORT
if (IsXML(lval) && IsXML(rval)) {
if (!js_ConcatenateXML(cx, &lval.toObject(), &rval.toObject(), res))
if (IsXML(lhs) && IsXML(rhs)) {
if (!js_ConcatenateXML(cx, &lhs.toObject(), &rhs.toObject(), res))
return false;
types::TypeScript::MonitorUnknown(cx);
} else
#endif
{
RootedVarValue lval_(cx, lhs);
RootedVarValue rval_(cx, rhs);
Value &lval = lval_.reference();
Value &rval = rval_.reference();
/*
* If either operand is an object, any non-integer result must be
* reported to inference.
@ -565,22 +574,22 @@ AddOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
return false;
bool lIsString, rIsString;
if ((lIsString = lval.isString()) | (rIsString = rval.isString())) {
js::AutoStringRooter lstr(cx), rstr(cx);
RootedVarString lstr(cx), rstr(cx);
if (lIsString) {
lstr.setString(lval.toString());
lstr = lval.toString();
} else {
lstr.setString(ToString(cx, lval));
if (!lstr.string())
lstr = ToString(cx, lval);
if (!lstr)
return false;
}
if (rIsString) {
rstr.setString(rval.toString());
rstr = rval.toString();
} else {
rstr.setString(ToString(cx, rval));
if (!rstr.string())
rstr = ToString(cx, rval);
if (!rstr)
return false;
}
JSString *str = js_ConcatStrings(cx, lstr.string(), rstr.string());
JSString *str = js_ConcatStrings(cx, lstr, rstr);
if (!str)
return false;
if (lIsObject || rIsObject)
@ -693,7 +702,7 @@ ToIdOperation(JSContext *cx, const Value &objval, const Value &idval, Value *res
}
static JS_ALWAYS_INLINE bool
GetObjectElementOperation(JSContext *cx, JSOp op, JSObject *obj, const Value &rref, Value *res)
GetObjectElementOperation(JSContext *cx, JSOp op, HandleObject obj, const Value &rref, Value *res)
{
#if JS_HAS_XML_SUPPORT
if (op == JSOP_CALLELEM && JS_UNLIKELY(obj->isXML())) {
@ -773,7 +782,7 @@ GetElementOperation(JSContext *cx, JSOp op, const Value &lref, const Value &rref
return NormalArgumentsObject::optimizedGetElem(cx, cx->fp(), rref, res);
bool isObject = lref.isObject();
JSObject *obj = ValueToObject(cx, lref);
RootedVarObject obj(cx, ValueToObject(cx, lref));
if (!obj)
return false;
if (!GetObjectElementOperation(cx, op, obj, rref, res))
@ -817,8 +826,8 @@ SetObjectElementOperation(JSContext *cx, JSObject *obj, jsid id, const Value &va
}
} while (0);
Value tmp = value;
return obj->setGeneric(cx, id, &tmp, strict);
RootedVarValue tmp(cx, value);
return obj->setGeneric(cx, id, tmp.address(), strict);
}
#define RELATIONAL_OP(OP) \

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

@ -443,7 +443,7 @@ js::GetPropertyNames(JSContext *cx, JSObject *obj, unsigned flags, AutoIdVector
size_t sCustomIteratorCount = 0;
static inline bool
GetCustomIterator(JSContext *cx, JSObject *obj, unsigned flags, Value *vp)
GetCustomIterator(JSContext *cx, HandleObject obj, unsigned flags, Value *vp)
{
JS_CHECK_RECURSION(cx, return false);
@ -584,7 +584,7 @@ RegisterEnumerator(JSContext *cx, JSObject *iterobj, NativeIterator *ni)
}
static inline bool
VectorToKeyIterator(JSContext *cx, JSObject *obj, unsigned flags, AutoIdVector &keys,
VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &keys,
uint32_t slength, uint32_t key, Value *vp)
{
JS_ASSERT(!(flags & JSITER_FOREACH));
@ -595,7 +595,7 @@ VectorToKeyIterator(JSContext *cx, JSObject *obj, unsigned flags, AutoIdVector &
types::MarkTypeObjectFlags(cx, obj, types::OBJECT_FLAG_ITERATED);
}
JSObject *iterobj = NewIteratorObject(cx, flags);
RootedVarObject iterobj(cx, NewIteratorObject(cx, flags));
if (!iterobj)
return false;
@ -631,13 +631,13 @@ VectorToKeyIterator(JSContext *cx, JSObject *obj, unsigned flags, AutoIdVector &
namespace js {
bool
VectorToKeyIterator(JSContext *cx, JSObject *obj, unsigned flags, AutoIdVector &props, Value *vp)
VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, Value *vp)
{
return VectorToKeyIterator(cx, obj, flags, props, 0, 0, vp);
}
bool
VectorToValueIterator(JSContext *cx, JSObject *obj, unsigned flags, AutoIdVector &keys,
VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &keys,
Value *vp)
{
JS_ASSERT(flags & JSITER_FOREACH);
@ -665,7 +665,7 @@ VectorToValueIterator(JSContext *cx, JSObject *obj, unsigned flags, AutoIdVector
}
bool
EnumeratedIdVectorToIterator(JSContext *cx, JSObject *obj, unsigned flags, AutoIdVector &props, Value *vp)
EnumeratedIdVectorToIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, Value *vp)
{
if (!(flags & JSITER_FOREACH))
return VectorToKeyIterator(cx, obj, flags, props, vp);
@ -682,7 +682,7 @@ UpdateNativeIterator(NativeIterator *ni, JSObject *obj)
}
bool
GetIterator(JSContext *cx, JSObject *obj, unsigned flags, Value *vp)
GetIterator(JSContext *cx, HandleObject obj, unsigned flags, Value *vp)
{
Vector<const Shape *, 8> shapes(cx);
uint32_t key = 0;
@ -849,7 +849,7 @@ iterator_next(JSContext *cx, unsigned argc, Value *vp)
CallArgs args = CallArgsFromVp(argc, vp);
bool ok;
JSObject *obj = NonGenericMethodGuard(cx, args, iterator_next, &IteratorClass, &ok);
RootedVarObject obj(cx, NonGenericMethodGuard(cx, args, iterator_next, &IteratorClass, &ok));
if (!obj)
return ok;
@ -893,7 +893,7 @@ js::ValueToIterator(JSContext *cx, unsigned flags, Value *vp)
*/
cx->iterValue.setMagic(JS_NO_ITER_VALUE);
JSObject *obj;
RootedVarObject obj(cx);
if (vp->isObject()) {
/* Common case. */
obj = &vp->toObject();
@ -906,7 +906,7 @@ js::ValueToIterator(JSContext *cx, unsigned flags, Value *vp)
* standard.
*/
if ((flags & JSITER_ENUMERATE)) {
if (!js_ValueToObjectOrNull(cx, *vp, &obj))
if (!js_ValueToObjectOrNull(cx, *vp, obj.address()))
return false;
/* fall through */
} else {
@ -1154,7 +1154,7 @@ bool
ElementIteratorObject::iteratorNext(JSContext *cx, Value *vp)
{
uint32_t i, length;
JSObject *obj = getTargetObject();
RootedVarObject obj(cx, getTargetObject());
if (!js_GetLengthProperty(cx, obj, &length))
goto error;
@ -1186,7 +1186,7 @@ JSObject::asElementIterator()
}
JSBool
js_IteratorMore(JSContext *cx, JSObject *iterobj, Value *rval)
js_IteratorMore(JSContext *cx, HandleObject iterobj, Value *rval)
{
/* Fast path for native iterators */
NativeIterator *ni = NULL;

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

@ -163,23 +163,23 @@ class ElementIteratorObject : public JSObject {
};
bool
VectorToIdArray(JSContext *cx, js::AutoIdVector &props, JSIdArray **idap);
VectorToIdArray(JSContext *cx, AutoIdVector &props, JSIdArray **idap);
bool
GetIterator(JSContext *cx, JSObject *obj, unsigned flags, js::Value *vp);
GetIterator(JSContext *cx, HandleObject obj, unsigned flags, Value *vp);
bool
VectorToKeyIterator(JSContext *cx, JSObject *obj, unsigned flags, js::AutoIdVector &props, js::Value *vp);
VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, Value *vp);
bool
VectorToValueIterator(JSContext *cx, JSObject *obj, unsigned flags, js::AutoIdVector &props, js::Value *vp);
VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, Value *vp);
/*
* Creates either a key or value iterator, depending on flags. For a value
* iterator, performs value-lookup to convert the given list of jsids.
*/
bool
EnumeratedIdVectorToIterator(JSContext *cx, JSObject *obj, unsigned flags, js::AutoIdVector &props, js::Value *vp);
EnumeratedIdVectorToIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, Value *vp);
/*
* Convert the value stored in *vp to its iteration object. The flags should
@ -188,7 +188,7 @@ EnumeratedIdVectorToIterator(JSContext *cx, JSObject *obj, unsigned flags, js::A
* iterator will never be exposed to scripts.
*/
extern JSBool
ValueToIterator(JSContext *cx, unsigned flags, js::Value *vp);
ValueToIterator(JSContext *cx, unsigned flags, Value *vp);
extern bool
CloseIterator(JSContext *cx, JSObject *iterObj);
@ -216,7 +216,7 @@ js_SuppressDeletedElements(JSContext *cx, JSObject *obj, uint32_t begin, uint32_
* picked up by IteratorNext(). The value is cached in the current context.
*/
extern JSBool
js_IteratorMore(JSContext *cx, JSObject *iterobj, js::Value *rval);
js_IteratorMore(JSContext *cx, js::HandleObject iterobj, js::Value *rval);
extern JSBool
js_IteratorNext(JSContext *cx, JSObject *iterobj, js::Value *rval);
@ -233,7 +233,7 @@ namespace js {
* more values, store the magic value JS_NO_ITER_VALUE in *vp and return true.
*/
inline bool
Next(JSContext *cx, JSObject *iter, Value *vp)
Next(JSContext *cx, HandleObject iter, Value *vp)
{
if (!js_IteratorMore(cx, iter, vp))
return false;
@ -262,7 +262,7 @@ ForOf(JSContext *cx, const Value &iterable, Op op)
Value iterv(iterable);
if (!ValueToIterator(cx, JSITER_FOR_OF, &iterv))
return false;
JSObject *iter = &iterv.toObject();
RootedVarObject iter(cx, &iterv.toObject());
bool ok = true;
while (ok) {

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

@ -711,9 +711,11 @@ js_IsMathFunction(Native native)
}
JSObject *
js_InitMathClass(JSContext *cx, JSObject *obj)
js_InitMathClass(JSContext *cx, JSObject *obj_)
{
JSObject *Math = NewObjectWithClassProto(cx, &MathClass, NULL, obj);
RootedVarObject obj(cx, obj_);
RootedVarObject Math(cx, NewObjectWithClassProto(cx, &MathClass, NULL, obj));
if (!Math || !Math->setSingletonType(cx))
return NULL;

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

@ -1014,14 +1014,15 @@ js_InitNumberClass(JSContext *cx, JSObject *obj)
/* XXX must do at least once per new thread, so do it per JSContext... */
FIX_FPU();
GlobalObject *global = &obj->asGlobal();
RootedVar<GlobalObject*> global(cx, &obj->asGlobal());
JSObject *numberProto = global->createBlankPrototype(cx, &NumberClass);
RootedVarObject numberProto(cx, global->createBlankPrototype(cx, &NumberClass));
if (!numberProto)
return NULL;
numberProto->asNumber().setPrimitiveValue(0);
JSFunction *ctor = global->createConstructor(cx, Number, CLASS_ATOM(cx, Number), 1);
RootedVarFunction ctor(cx);
ctor = global->createConstructor(cx, Number, CLASS_ATOM(cx, Number), 1);
if (!ctor)
return NULL;

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

@ -846,13 +846,13 @@ class EvalScriptGuard
JSContext *cx_;
JSLinearString *str_;
JSScript **bucket_;
JSScript *script_;
RootedVar<JSScript*> script_;
public:
EvalScriptGuard(JSContext *cx, JSLinearString *str)
: cx_(cx),
str_(str),
script_(NULL) {
script_(cx) {
bucket_ = EvalCacheHash(cx, str);
}
@ -909,12 +909,12 @@ enum EvalType { DIRECT_EVAL = EXECUTE_DIRECT_EVAL, INDIRECT_EVAL = EXECUTE_INDIR
*/
static bool
EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *caller,
JSObject &scopeobj)
HandleObject scopeobj)
{
JS_ASSERT((evalType == INDIRECT_EVAL) == (caller == NULL));
AssertInnerizedScopeChain(cx, scopeobj);
AssertInnerizedScopeChain(cx, *scopeobj);
if (!scopeobj.global().isRuntimeCodeGenEnabled(cx)) {
if (!scopeobj->global().isRuntimeCodeGenEnabled(cx)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_EVAL);
return false;
}
@ -956,11 +956,11 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
JS_ASSERT(callerPC && JSOp(*callerPC) == JSOP_EVAL);
#endif
} else {
JS_ASSERT(args.callee().global() == scopeobj);
JS_ASSERT(args.callee().global() == *scopeobj);
staticLevel = 0;
/* Use the global as 'this', modulo outerization. */
JSObject *thisobj = scopeobj.thisObject(cx);
JSObject *thisobj = scopeobj->thisObject(cx);
if (!thisobj)
return false;
thisv = ObjectValue(*thisobj);
@ -1020,7 +1020,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
JSPrincipals *principals = PrincipalsForCompiledCode(args, cx);
if (evalType == DIRECT_EVAL && caller->isNonEvalFunctionFrame())
esg.lookupInEvalCache(caller, staticLevel, principals, scopeobj);
esg.lookupInEvalCache(caller, staticLevel, principals, *scopeobj);
if (!esg.foundScript()) {
unsigned lineno;
@ -1030,7 +1030,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
evalType == DIRECT_EVAL ? CALLED_FROM_JSOP_EVAL
: NOT_CALLED_FROM_JSOP_EVAL);
uint32_t tcflags = TCF_COMPILE_N_GO | TCF_COMPILE_FOR_EVAL;
JSScript *compiled = frontend::CompileScript(cx, &scopeobj, caller,
JSScript *compiled = frontend::CompileScript(cx, scopeobj, caller,
principals, originPrincipals,
tcflags, chars, length, filename,
lineno, cx->findVersion(), linearStr,
@ -1041,7 +1041,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
esg.setNewScript(compiled);
}
return ExecuteKernel(cx, esg.script(), scopeobj, thisv, ExecuteType(evalType),
return ExecuteKernel(cx, esg.script(), *scopeobj, thisv, ExecuteType(evalType),
NULL /* evalInFrame */, &args.rval());
}
@ -1086,7 +1086,8 @@ eval(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return WarnOnTooManyArgs(cx, args) &&
EvalKernel(cx, args, INDIRECT_EVAL, NULL, args.callee().global());
EvalKernel(cx, args, INDIRECT_EVAL, NULL,
RootedVarObject(cx, &args.callee().global()));
}
bool
@ -1100,14 +1101,14 @@ DirectEval(JSContext *cx, const CallArgs &args)
AutoFunctionCallProbe callProbe(cx, args.callee().toFunction(), caller->script());
JSObject *scopeChain = GetScopeChain(cx, caller);
RootedVarObject scopeChain(cx, GetScopeChain(cx, caller));
if (!scopeChain)
return false;
if (!WarnOnTooManyArgs(cx, args))
return false;
return EvalKernel(cx, args, DIRECT_EVAL, caller, *scopeChain);
return EvalKernel(cx, args, DIRECT_EVAL, caller, scopeChain);
}
bool
@ -1194,7 +1195,7 @@ obj_watch(JSContext *cx, unsigned argc, Value *vp)
if (!ValueToId(cx, vp[2], &propid))
return false;
JSObject *obj = ToObject(cx, &vp[1]);
RootedVarObject obj(cx, ToObject(cx, &vp[1]));
if (!obj)
return false;
@ -1205,7 +1206,7 @@ obj_watch(JSContext *cx, unsigned argc, Value *vp)
vp->setUndefined();
if (obj->isDenseArray() && !obj->makeDenseArraySlow(cx))
if (obj->isDenseArray() && !JSObject::makeDenseArraySlow(cx, obj))
return false;
return JS_SetWatchPoint(cx, obj, propid, obj_watch_handler, callable);
}
@ -1252,7 +1253,7 @@ js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, unsigned argc,
if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), &id))
return JS_FALSE;
JSObject *obj = ToObject(cx, &vp[1]);
RootedVarObject obj(cx, ToObject(cx, &vp[1]));
if (!obj)
return false;
JSObject *obj2;
@ -1271,7 +1272,7 @@ js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, unsigned argc,
}
JSBool
js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, JSObject *obj, jsid id,
js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, jsid id,
JSObject **objp, JSProperty **propp)
{
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING);
@ -1410,8 +1411,13 @@ DefineAccessor(JSContext *cx, unsigned argc, Value *vp)
return false;
JSBool dummy;
if (!js_DefineOwnProperty(cx, &args.thisv().toObject(), id, ObjectValue(*descObj), &dummy))
if (!js_DefineOwnProperty(cx,
RootedVarObject(cx, &args.thisv().toObject()),
RootedVarId(cx, id),
ObjectValue(*descObj), &dummy))
{
return false;
}
args.rval().setUndefined();
return true;
}
@ -1583,7 +1589,7 @@ PropDesc::makeObject(JSContext *cx)
}
bool
GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, PropertyDescriptor *desc)
GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, PropertyDescriptor *desc)
{
if (obj->isProxy())
return Proxy::getOwnPropertyDescriptor(cx, obj, id, false, desc);
@ -1621,7 +1627,7 @@ GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, PropertyDescript
}
bool
GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, Value *vp)
GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
{
AutoPropertyDescriptorRooter desc(cx);
return GetOwnPropertyDescriptor(cx, obj, id, &desc) &&
@ -1657,13 +1663,13 @@ GetFirstArgumentAsObject(JSContext *cx, unsigned argc, Value *vp, const char *me
static JSBool
obj_getOwnPropertyDescriptor(JSContext *cx, unsigned argc, Value *vp)
{
JSObject *obj;
if (!GetFirstArgumentAsObject(cx, argc, vp, "Object.getOwnPropertyDescriptor", &obj))
RootedVarObject obj(cx);
if (!GetFirstArgumentAsObject(cx, argc, vp, "Object.getOwnPropertyDescriptor", obj.address()))
return JS_FALSE;
AutoIdRooter nameidr(cx);
if (!ValueToId(cx, argc >= 2 ? vp[3] : UndefinedValue(), nameidr.addr()))
RootedVarId id(cx);
if (!ValueToId(cx, argc >= 2 ? vp[3] : UndefinedValue(), id.address()))
return JS_FALSE;
return GetOwnPropertyDescriptor(cx, obj, nameidr.id(), vp);
return GetOwnPropertyDescriptor(cx, obj, id, vp);
}
static JSBool
@ -1884,14 +1890,14 @@ Reject(JSContext *cx, JSObject *obj, unsigned errorNumber, bool throwError, bool
}
static JSBool
DefinePropertyOnObject(JSContext *cx, JSObject *obj, const jsid &id, const PropDesc &desc,
DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc,
bool throwError, bool *rval)
{
/* 8.12.9 step 1. */
JSProperty *current;
JSObject *obj2;
RootedVarObject obj2(cx);
JS_ASSERT(!obj->getOps()->lookupGeneric);
if (!js_HasOwnProperty(cx, NULL, obj, id, &obj2, &current))
if (!js_HasOwnProperty(cx, NULL, obj, id, obj2.address(), &current))
return JS_FALSE;
JS_ASSERT(!obj->getOps()->defineProperty);
@ -2184,7 +2190,7 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const jsid &id, const PropD
}
static JSBool
DefinePropertyOnArray(JSContext *cx, JSObject *obj, const jsid &id, const PropDesc &desc,
DefinePropertyOnArray(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc,
bool throwError, bool *rval)
{
/*
@ -2194,7 +2200,7 @@ DefinePropertyOnArray(JSContext *cx, JSObject *obj, const jsid &id, const PropDe
* attributes). Such definitions are probably unlikely, so we don't bother
* for now.
*/
if (obj->isDenseArray() && !obj->makeDenseArraySlow(cx))
if (obj->isDenseArray() && !JSObject::makeDenseArraySlow(cx, obj))
return JS_FALSE;
uint32_t oldLen = obj->getArrayLength();
@ -2238,7 +2244,7 @@ DefinePropertyOnArray(JSContext *cx, JSObject *obj, const jsid &id, const PropDe
namespace js {
bool
DefineProperty(JSContext *cx, JSObject *obj, const jsid &id, const PropDesc &desc, bool throwError,
DefineProperty(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc, bool throwError,
bool *rval)
{
if (obj->isArray())
@ -2256,7 +2262,7 @@ DefineProperty(JSContext *cx, JSObject *obj, const jsid &id, const PropDesc &des
} /* namespace js */
JSBool
js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, const Value &descriptor, JSBool *bp)
js_DefineOwnProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &descriptor, JSBool *bp)
{
AutoPropDescArrayRooter descs(cx);
PropDesc *desc = descs.append();
@ -2274,12 +2280,12 @@ js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, const Value &descrip
static JSBool
obj_defineProperty(JSContext *cx, unsigned argc, Value *vp)
{
JSObject *obj;
if (!GetFirstArgumentAsObject(cx, argc, vp, "Object.defineProperty", &obj))
RootedVarObject obj(cx);
if (!GetFirstArgumentAsObject(cx, argc, vp, "Object.defineProperty", obj.address()))
return false;
jsid id;
if (!ValueToId(cx, argc >= 2 ? vp[3] : UndefinedValue(), &id))
RootedVarId id(cx);
if (!ValueToId(cx, argc >= 2 ? vp[3] : UndefinedValue(), id.address()))
return JS_FALSE;
const Value descval = argc >= 3 ? vp[4] : UndefinedValue();
@ -2314,7 +2320,7 @@ ReadPropertyDescriptors(JSContext *cx, JSObject *props, bool checkAccessors,
} /* namespace js */
static bool
DefineProperties(JSContext *cx, JSObject *obj, JSObject *props)
DefineProperties(JSContext *cx, HandleObject obj, JSObject *props)
{
AutoIdVector ids(cx);
AutoPropDescArrayRooter descs(cx);
@ -2323,7 +2329,7 @@ DefineProperties(JSContext *cx, JSObject *obj, JSObject *props)
bool dummy;
for (size_t i = 0, len = ids.length(); i < len; i++) {
if (!DefineProperty(cx, obj, ids[i], descs[i], true, &dummy))
if (!DefineProperty(cx, obj, RootedVarId(cx, ids[i]), descs[i], true, &dummy))
return false;
}
@ -2331,7 +2337,7 @@ DefineProperties(JSContext *cx, JSObject *obj, JSObject *props)
}
extern JSBool
js_PopulateObject(JSContext *cx, JSObject *newborn, JSObject *props)
js_PopulateObject(JSContext *cx, HandleObject newborn, JSObject *props)
{
return DefineProperties(cx, newborn, props);
}
@ -2341,8 +2347,8 @@ static JSBool
obj_defineProperties(JSContext *cx, unsigned argc, Value *vp)
{
/* Steps 1 and 7. */
JSObject *obj;
if (!GetFirstArgumentAsObject(cx, argc, vp, "Object.defineProperties", &obj))
RootedVarObject obj(cx);
if (!GetFirstArgumentAsObject(cx, argc, vp, "Object.defineProperties", obj.address()))
return false;
vp->setObject(*obj);
@ -2392,7 +2398,8 @@ obj_create(JSContext *cx, unsigned argc, Value *vp)
* Use the callee's global as the parent of the new object to avoid dynamic
* scoping (i.e., using the caller's global).
*/
JSObject *obj = NewObjectWithGivenProto(cx, &ObjectClass, proto, &args.callee().global());
RootedVarObject obj(cx);
obj = NewObjectWithGivenProto(cx, &ObjectClass, proto, &args.callee().global());
if (!obj)
return false;
@ -2507,7 +2514,7 @@ JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
/* preventExtensions must slowify dense arrays, so we can assign to holes without checks. */
JS_ASSERT(!self->isDenseArray());
if (isNative() && !inDictionaryMode()) {
if (self->isNative() && !self->inDictionaryMode()) {
/*
* Seal/freeze non-dictionary objects by constructing a new shape
* hierarchy mirroring the original one, which can be shared if many
@ -2544,7 +2551,7 @@ JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
}
JS_ASSERT(self->lastProperty()->slotSpan() == last->slotSpan());
JS_ALWAYS_TRUE(setLastProperty(cx, last));
JS_ALWAYS_TRUE(self->setLastProperty(cx, last));
} else {
for (size_t i = 0; i < props.length(); i++) {
jsid id = props[i];
@ -2858,7 +2865,7 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
}
JSObject *
js::NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc::AllocKind kind)
js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind kind)
{
JS_ASSERT(type->proto->hasNewType(type));
JS_ASSERT(parent);
@ -2885,10 +2892,10 @@ js::NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent,
}
JSObject *
js::NewReshapedObject(JSContext *cx, TypeObject *type, JSObject *parent,
js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
gc::AllocKind kind, const Shape *shape)
{
JSObject *res = NewObjectWithType(cx, type, parent, kind);
RootedVarObject res(cx, NewObjectWithType(cx, type, parent, kind));
if (!res)
return NULL;
@ -2933,7 +2940,7 @@ js_CreateThis(JSContext *cx, Class *newclasp, JSObject *callee)
}
static inline JSObject *
CreateThisForFunctionWithType(JSContext *cx, types::TypeObject *type, JSObject *parent)
CreateThisForFunctionWithType(JSContext *cx, HandleTypeObject type, JSObject *parent)
{
if (type->newScript) {
/*
@ -2953,12 +2960,12 @@ CreateThisForFunctionWithType(JSContext *cx, types::TypeObject *type, JSObject *
}
JSObject *
js_CreateThisForFunctionWithProto(JSContext *cx, JSObject *callee, JSObject *proto)
js_CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject *proto)
{
JSObject *res;
if (proto) {
types::TypeObject *type = proto->getNewType(cx, callee->toFunction());
RootedVarTypeObject type(cx, proto->getNewType(cx, callee->toFunction()));
if (!type)
return NULL;
res = CreateThisForFunctionWithType(cx, type, callee->getParent());
@ -2974,7 +2981,7 @@ js_CreateThisForFunctionWithProto(JSContext *cx, JSObject *callee, JSObject *pro
}
JSObject *
js_CreateThisForFunction(JSContext *cx, JSObject *callee, bool newType)
js_CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType)
{
Value protov;
if (!callee->getProperty(cx, cx->runtime->atomState.classPrototypeAtom, &protov))
@ -3191,15 +3198,19 @@ CopySlots(JSContext *cx, JSObject *from, JSObject *to)
}
JS_FRIEND_API(JSObject *)
JS_CloneObject(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent)
JS_CloneObject(JSContext *cx, JSObject *obj_, JSObject *proto_, JSObject *parent_)
{
RootedVarObject obj(cx, obj_);
RootedVarObject proto(cx, proto_);
RootedVarObject parent(cx, parent_);
/*
* We can only clone native objects and proxies. Dense arrays are slowified if
* we try to clone them.
*/
if (!obj->isNative()) {
if (obj->isDenseArray()) {
if (!obj->makeDenseArraySlow(cx))
if (!JSObject::makeDenseArraySlow(cx, obj))
return NULL;
} else if (!obj->isProxy()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
@ -3632,7 +3643,7 @@ DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, H
if (!proto->setSingletonType(cx))
return NULL;
if (clasp == &ArrayClass && !proto->makeDenseArraySlow(cx))
if (clasp == &ArrayClass && !JSObject::makeDenseArraySlow(cx, proto))
return NULL;
/* After this point, control must exit via label bad or out. */
@ -3903,7 +3914,8 @@ JSObject::growSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount)
gc::AllocKind kind = type()->newScript->allocKind;
unsigned newScriptSlots = gc::GetGCKindSlots(kind);
if (newScriptSlots == numFixedSlots() && gc::TryIncrementAllocKind(&kind)) {
JSObject *obj = NewReshapedObject(cx, type(), getParent(), kind,
JSObject *obj = NewReshapedObject(cx, RootedVarTypeObject(cx, type()),
getParent(), kind,
type()->newScript->shape);
if (!obj)
return false;
@ -4421,16 +4433,18 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
}
JSBool
js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value,
js_DefineProperty(JSContext *cx, JSObject *obj_, jsid id, const Value *value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
RootObject obj(cx, &obj_);
return !!DefineNativeProperty(cx, obj, id, *value, getter, setter, attrs, 0, 0);
}
JSBool
js_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
js_DefineElement(JSContext *cx, JSObject *obj_, uint32_t index, const Value *value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
RootObject obj(cx, &obj_);
jsid id;
if (!IndexToId(cx, index, &id))
return false;
@ -4462,7 +4476,7 @@ CallAddPropertyHook(JSContext *cx, Class *clasp, JSObject *obj, const Shape *sha
namespace js {
const Shape *
DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_,
DefineNativeProperty(JSContext *cx, HandleObject obj, jsid id, const Value &value_,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow /* = 0 */)
{
@ -4470,7 +4484,6 @@ DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_,
DNP_SKIP_TYPE)) == 0);
JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
RootObject objRoot(cx, &obj);
RootId idRoot(cx, &id);
/* Make a local copy of value so addProperty can mutate its inout parameter. */
@ -4654,17 +4667,17 @@ CallResolveOp(JSContext *cx, JSObject *start, HandleObject obj, HandleId id, uns
}
static JS_ALWAYS_INLINE bool
LookupPropertyWithFlagsInline(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
LookupPropertyWithFlagsInline(JSContext *cx, JSObject *obj_, jsid id_, unsigned flags,
JSObject **objp, JSProperty **propp)
{
/* We should not get string indices which aren't already integers here. */
JS_ASSERT(id == js_CheckForStringIndex(id));
RootedVarObject obj(cx, obj_);
RootedVarId id(cx, id_);
RootObject objRoot(cx, &obj);
RootId idRoot(cx, &id);
/* We should not get string indices which aren't already integers here. */
JS_ASSERT(id.raw() == js_CheckForStringIndex(id));
/* Search scopes starting with obj and following the prototype link. */
JSObject *start = obj;
RootedVarObject start(cx, obj);
while (true) {
const Shape *shape = obj->nativeLookup(cx, id);
if (shape) {
@ -4676,7 +4689,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, JSObject *obj, jsid id, unsigned fl
/* Try obj's class resolve hook if id was not found in obj's scope. */
if (obj->getClass()->resolve != JS_ResolveStub) {
bool recursed;
if (!CallResolveOp(cx, start, objRoot, idRoot, flags, objp, propp, &recursed))
if (!CallResolveOp(cx, start, obj, id, flags, objp, propp, &recursed))
return false;
if (recursed)
break;
@ -4752,17 +4765,19 @@ js::LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, unsigned flag
}
bool
js::FindPropertyHelper(JSContext *cx, PropertyName *name, bool cacheResult, JSObject *scopeChain,
js::FindPropertyHelper(JSContext *cx,
HandlePropertyName name, bool cacheResult, HandleObject scopeChain,
JSObject **objp, JSObject **pobjp, JSProperty **propp)
{
jsid id = ATOM_TO_JSID(name);
JSObject *obj, *parent, *pobj;
RootedVarId id(cx, ATOM_TO_JSID(name));
JSObject *pobj;
int scopeIndex;
JSProperty *prop;
/* Scan entries on the scope chain that we can cache across. */
obj = scopeChain;
parent = obj->enclosingScope();
RootedVarObject obj(cx, scopeChain);
RootedVarObject parent(cx, obj->enclosingScope());
for (scopeIndex = 0;
parent
? IsCacheableNonGlobalScope(obj)
@ -4844,7 +4859,7 @@ js::FindPropertyHelper(JSContext *cx, PropertyName *name, bool cacheResult, JSOb
* Otherwise, its type and meaning depends on the host object's implementation.
*/
bool
js::FindProperty(JSContext *cx, PropertyName *name, JSObject *scopeChain,
js::FindProperty(JSContext *cx, HandlePropertyName name, HandleObject scopeChain,
JSObject **objp, JSObject **pobjp, JSProperty **propp)
{
return !!FindPropertyHelper(cx, name, false, scopeChain, objp, pobjp, propp);
@ -4940,6 +4955,9 @@ js_NativeGetInline(JSContext *cx, JSObject *receiver, JSObject *obj, JSObject *p
code->accessGetter = true;
}
Root<const Shape*> rootShape(cx, &shape);
RootObject pobjRoot(cx, &pobj);
if (!shape->get(cx, receiver, obj, pobj, vp))
return false;
@ -4983,6 +5001,9 @@ js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, bool
return js_ReportGetterOnlyAssignment(cx);
}
RootObject objRoot(cx, &obj);
Root<const Shape *> shapeRoot(cx, &shape);
int32_t sample = cx->runtime->propertyRemovals;
if (!shape->set(cx, obj, strict, vp))
return false;
@ -5001,19 +5022,19 @@ js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, bool
}
static JS_ALWAYS_INLINE JSBool
js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id,
js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receiver, jsid id_,
uint32_t getHow, Value *vp)
{
JSObject *aobj, *obj2;
JSProperty *prop;
const Shape *shape;
RootedVarId id(cx, id_);
/* Convert string indices to integers if appropriate. */
id = js_CheckForStringIndex(id);
aobj = js_GetProtoIfDenseArray(obj);
/* This call site is hot -- use the always-inlined variant of LookupPropertyWithFlags(). */
if (!LookupPropertyWithFlagsInline(cx, aobj, id, cx->resolveFlags, &obj2, &prop))
RootedVarObject obj2(cx);
if (!LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, obj2.address(), &prop))
return false;
if (!prop) {
@ -5084,10 +5105,10 @@ js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsi
: obj2->getGeneric(cx, id, vp);
}
shape = (Shape *) prop;
Shape *shape = (Shape *) prop;
if (getHow & JSGET_CACHE_RESULT)
JS_PROPERTY_CACHE(cx).fill(cx, aobj, 0, obj2, shape);
JS_PROPERTY_CACHE(cx).fill(cx, obj, 0, 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))
@ -5097,20 +5118,20 @@ js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsi
}
bool
js::GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32_t getHow, Value *vp)
js::GetPropertyHelper(JSContext *cx, HandleObject obj, jsid id, uint32_t getHow, Value *vp)
{
return !!js_GetPropertyHelperInline(cx, obj, obj, id, getHow, vp);
}
JSBool
js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
js_GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, jsid id, Value *vp)
{
/* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */
return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp);
}
JSBool
js_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp)
js_GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp)
{
jsid id;
if (!IndexToId(cx, index, &id))
@ -5121,11 +5142,11 @@ js_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index,
}
JSBool
js::GetPropertyDefault(JSContext *cx, JSObject *obj, jsid id, const Value &def, Value *vp)
js::GetPropertyDefault(JSContext *cx, HandleObject obj, HandleId id, const Value &def, Value *vp)
{
JSProperty *prop;
JSObject *obj2;
if (!LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
RootedVarObject obj2(cx);
if (!LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, obj2.address(), &prop))
return false;
if (!prop) {
@ -5137,7 +5158,7 @@ js::GetPropertyDefault(JSContext *cx, JSObject *obj, jsid id, const Value &def,
}
JSBool
js_GetMethod(JSContext *cx, JSObject *obj, jsid id, unsigned getHow, Value *vp)
js_GetMethod(JSContext *cx, HandleObject obj, jsid id, unsigned getHow, Value *vp)
{
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
@ -5205,17 +5226,16 @@ bool
JSObject::callMethod(JSContext *cx, jsid id, unsigned argc, Value *argv, Value *vp)
{
Value fval;
return js_GetMethod(cx, this, id, 0, &fval) &&
return js_GetMethod(cx, RootedVarObject(cx, this), id, 0, &fval) &&
Invoke(cx, ObjectValue(*this), fval, argc, argv, vp);
}
JSBool
js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow,
js_SetPropertyHelper(JSContext *cx, HandleObject obj, jsid id, unsigned defineHow,
Value *vp, JSBool strict)
{
JSObject *pobj;
JSProperty *prop;
const Shape *shape;
unsigned attrs, flags;
int shortid;
Class *clasp;
@ -5224,6 +5244,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow,
bool added;
JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_UNQUALIFIED)) == 0);
RootId idRoot(cx, &id);
/* Convert string indices to integers if appropriate. */
id = js_CheckForStringIndex(id);
@ -5270,7 +5291,8 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow,
return JS_FALSE;
}
}
shape = (Shape *) prop;
RootedVarShape shape(cx, (Shape *) prop);
/*
* Now either shape is null, meaning id was not found in obj or one of its
@ -5398,7 +5420,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow,
}
JSBool
js_SetElementHelper(JSContext *cx, JSObject *obj, uint32_t index, unsigned defineHow,
js_SetElementHelper(JSContext *cx, HandleObject obj, uint32_t index, unsigned defineHow,
Value *vp, JSBool strict)
{
jsid id;
@ -5536,7 +5558,7 @@ js_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBoo
namespace js {
bool
HasDataProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
HasDataProperty(JSContext *cx, HandleObject obj, jsid id, Value *vp)
{
JS_ASSERT(id == js_CheckForStringIndex(id));
if (const Shape *shape = obj->nativeLookup(cx, id)) {
@ -5558,7 +5580,7 @@ HasDataProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
* or steps 3-4.
*/
static bool
MaybeCallMethod(JSContext *cx, JSObject *obj, jsid id, Value *vp)
MaybeCallMethod(JSContext *cx, HandleObject obj, jsid id, Value *vp)
{
if (!js_GetMethod(cx, obj, id, 0, vp))
return false;
@ -5570,7 +5592,7 @@ MaybeCallMethod(JSContext *cx, JSObject *obj, jsid id, Value *vp)
}
JSBool
DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
DefaultValue(JSContext *cx, HandleObject obj, JSType hint, Value *vp)
{
JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
JS_ASSERT(!obj->isXML());
@ -5581,7 +5603,7 @@ DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
if (clasp == &StringClass &&
ClassMethodIsNative(cx, obj,
&StringClass,
ATOM_TO_JSID(cx->runtime->atomState.toStringAtom),
RootedVarId(cx, ATOM_TO_JSID(cx->runtime->atomState.toStringAtom)),
js_str_toString)) {
*vp = StringValue(obj->asString().unbox());
return true;
@ -5600,11 +5622,11 @@ DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
/* Optimize (new String(...)).valueOf(). */
if ((clasp == &StringClass &&
ClassMethodIsNative(cx, obj, &StringClass,
ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom),
RootedVarId(cx, ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom)),
js_str_toString)) ||
(clasp == &NumberClass &&
ClassMethodIsNative(cx, obj, &NumberClass,
ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom),
RootedVarId(cx, ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom)),
js_num_valueOf))) {
*vp = obj->isString()
? StringValue(obj->asString().unbox())
@ -5814,7 +5836,7 @@ JSObject *
PrimitiveToObject(JSContext *cx, const Value &v)
{
if (v.isString())
return StringObject::create(cx, v.toString());
return StringObject::create(cx, RootedVarString(cx, v.toString()));
if (v.isNumber())
return NumberObject::create(cx, v.toNumber());

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

@ -273,19 +273,19 @@ js_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, const js::Value *
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
extern JSBool
js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, js::Value *vp);
js_GetProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver, jsid id, js::Value *vp);
extern JSBool
js_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t, js::Value *vp);
js_GetElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver, uint32_t, js::Value *vp);
inline JSBool
js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp)
js_GetProperty(JSContext *cx, js::HandleObject obj, jsid id, js::Value *vp)
{
return js_GetProperty(cx, obj, obj, id, vp);
}
inline JSBool
js_GetElement(JSContext *cx, JSObject *obj, uint32_t index, js::Value *vp)
js_GetElement(JSContext *cx, js::HandleObject obj, uint32_t index, js::Value *vp)
{
return js_GetElement(cx, obj, obj, index, vp);
}
@ -293,18 +293,18 @@ js_GetElement(JSContext *cx, JSObject *obj, uint32_t index, js::Value *vp)
namespace js {
extern JSBool
GetPropertyDefault(JSContext *cx, JSObject *obj, jsid id, const Value &def, Value *vp);
GetPropertyDefault(JSContext *cx, js::HandleObject obj, js::HandleId id, const Value &def, Value *vp);
} /* namespace js */
extern JSBool
js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow,
js_SetPropertyHelper(JSContext *cx, js::HandleObject obj, jsid id, unsigned defineHow,
js::Value *vp, JSBool strict);
namespace js {
inline bool
SetPropertyHelper(JSContext *cx, JSObject *obj, PropertyName *name, unsigned defineHow,
SetPropertyHelper(JSContext *cx, HandleObject obj, PropertyName *name, unsigned defineHow,
Value *vp, JSBool strict)
{
return !!js_SetPropertyHelper(cx, obj, ATOM_TO_JSID(name), defineHow, vp, strict);
@ -313,7 +313,7 @@ SetPropertyHelper(JSContext *cx, JSObject *obj, PropertyName *name, unsigned def
} /* namespace js */
extern JSBool
js_SetElementHelper(JSContext *cx, JSObject *obj, uint32_t index, unsigned defineHow,
js_SetElementHelper(JSContext *cx, js::HandleObject obj, uint32_t index, unsigned defineHow,
js::Value *vp, JSBool strict);
extern JSBool
@ -347,7 +347,7 @@ namespace js {
/* ES5 8.12.8. */
extern JSBool
DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
DefaultValue(JSContext *cx, HandleObject obj, JSType hint, Value *vp);
extern Class ArrayClass;
extern Class ArrayBufferClass;
@ -739,7 +739,7 @@ struct JSObject : public js::ObjectImpl
*/
bool willBeSparseDenseArray(unsigned requiredCapacity, unsigned newElementsHint);
JSBool makeDenseArraySlow(JSContext *cx);
static bool makeDenseArraySlow(JSContext *cx, js::HandleObject obj);
/*
* If this array object has a data property with index i, set *vp to its
@ -1180,7 +1180,7 @@ js_HasOwnPropertyHelper(JSContext *cx, js::LookupGenericOp lookup, unsigned argc
js::Value *vp);
extern JSBool
js_HasOwnProperty(JSContext *cx, js::LookupGenericOp lookup, JSObject *obj, jsid id,
js_HasOwnProperty(JSContext *cx, js::LookupGenericOp lookup, js::HandleObject obj, jsid id,
JSObject **objp, JSProperty **propp);
extern JSBool
@ -1299,7 +1299,7 @@ extern const char js_lookupSetter_str[];
#endif
extern JSBool
js_PopulateObject(JSContext *cx, JSObject *newborn, JSObject *props);
js_PopulateObject(JSContext *cx, js::HandleObject newborn, JSObject *props);
/*
* Fast access to immutable standard objects (constructors and prototypes).
@ -1319,11 +1319,11 @@ js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey key,
// Specialized call for constructing |this| with a known function callee,
// and a known prototype.
extern JSObject *
js_CreateThisForFunctionWithProto(JSContext *cx, JSObject *callee, JSObject *proto);
js_CreateThisForFunctionWithProto(JSContext *cx, js::HandleObject callee, JSObject *proto);
// Specialized call for constructing |this| with a known function callee.
extern JSObject *
js_CreateThisForFunction(JSContext *cx, JSObject *callee, bool newType);
js_CreateThisForFunction(JSContext *cx, js::HandleObject callee, bool newType);
// Generic call for constructing |this|.
extern JSObject *
@ -1342,7 +1342,7 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
unsigned attrs, unsigned flags, int shortid);
extern JSBool
js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id,
js_DefineOwnProperty(JSContext *cx, js::HandleObject obj, js::HandleId id,
const js::Value &descriptor, JSBool *bp);
namespace js {
@ -1361,12 +1361,12 @@ const unsigned DNP_SKIP_TYPE = 8; /* Don't update type information */
* Return successfully added or changed shape or NULL on error.
*/
extern const Shape *
DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value,
DefineNativeProperty(JSContext *cx, HandleObject obj, jsid id, const Value &value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow = 0);
inline const Shape *
DefineNativeProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value &value,
DefineNativeProperty(JSContext *cx, HandleObject obj, PropertyName *name, const Value &value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow = 0)
{
@ -1397,7 +1397,8 @@ LookupPropertyWithFlags(JSContext *cx, JSObject *obj, PropertyName *name, unsign
* Otherwise, this reports an error and returns false.
*/
extern bool
DefineProperty(JSContext *cx, JSObject *obj, const jsid &id, const PropDesc &desc, bool throwError,
DefineProperty(JSContext *cx, js::HandleObject obj,
js::HandleId id, const PropDesc &desc, bool throwError,
bool *rval);
/*
@ -1418,7 +1419,8 @@ static const unsigned RESOLVE_INFER = 0xffff;
* If cacheResult is false, return JS_NO_PROP_CACHE_FILL on success.
*/
extern bool
FindPropertyHelper(JSContext *cx, PropertyName *name, bool cacheResult, JSObject *scopeChain,
FindPropertyHelper(JSContext *cx, HandlePropertyName name,
bool cacheResult, HandleObject scopeChain,
JSObject **objp, JSObject **pobjp, JSProperty **propp);
/*
@ -1426,7 +1428,7 @@ FindPropertyHelper(JSContext *cx, PropertyName *name, bool cacheResult, JSObject
* global object, per the global parameter.
*/
extern bool
FindProperty(JSContext *cx, PropertyName *name, JSObject *scopeChain,
FindProperty(JSContext *cx, HandlePropertyName name, HandleObject scopeChain,
JSObject **objp, JSObject **pobjp, JSProperty **propp);
extern JSObject *
@ -1457,19 +1459,19 @@ js_NativeSet(JSContext *cx, JSObject *obj, const js::Shape *shape, bool added,
namespace js {
bool
GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32_t getHow, Value *vp);
GetPropertyHelper(JSContext *cx, HandleObject obj, jsid id, uint32_t getHow, Value *vp);
inline bool
GetPropertyHelper(JSContext *cx, JSObject *obj, PropertyName *name, uint32_t getHow, Value *vp)
GetPropertyHelper(JSContext *cx, HandleObject obj, PropertyName *name, uint32_t getHow, Value *vp)
{
return GetPropertyHelper(cx, obj, ATOM_TO_JSID(name), getHow, vp);
}
bool
GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, PropertyDescriptor *desc);
GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, PropertyDescriptor *desc);
bool
GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, Value *vp);
GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, Value *vp);
bool
NewPropertyDescriptorObject(JSContext *cx, const PropertyDescriptor *desc, Value *vp);
@ -1477,12 +1479,12 @@ NewPropertyDescriptorObject(JSContext *cx, const PropertyDescriptor *desc, Value
} /* namespace js */
extern JSBool
js_GetMethod(JSContext *cx, JSObject *obj, jsid id, unsigned getHow, js::Value *vp);
js_GetMethod(JSContext *cx, js::HandleObject obj, jsid id, unsigned getHow, js::Value *vp);
namespace js {
inline bool
GetMethod(JSContext *cx, JSObject *obj, PropertyName *name, unsigned getHow, Value *vp)
GetMethod(JSContext *cx, HandleObject obj, PropertyName *name, unsigned getHow, Value *vp)
{
return js_GetMethod(cx, obj, ATOM_TO_JSID(name), getHow, vp);
}
@ -1497,10 +1499,10 @@ namespace js {
* called js_CheckForStringIndex.
*/
extern bool
HasDataProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp);
HasDataProperty(JSContext *cx, HandleObject obj, jsid id, Value *vp);
inline bool
HasDataProperty(JSContext *cx, JSObject *obj, JSAtom *atom, Value *vp)
HasDataProperty(JSContext *cx, HandleObject obj, JSAtom *atom, Value *vp)
{
return HasDataProperty(cx, obj, js_CheckForStringIndex(ATOM_TO_JSID(atom)), vp);
}

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

@ -96,7 +96,11 @@ inline bool
JSObject::defaultValue(JSContext *cx, JSType hint, js::Value *vp)
{
JSConvertOp op = getClass()->convert;
bool ok = (op == JS_ConvertStub ? js::DefaultValue : op)(cx, this, hint, vp);
bool ok;
if (op == JS_ConvertStub)
ok = js::DefaultValue(cx, js::RootedVarObject(cx, this), hint, vp);
else
ok = op(cx, this, hint, vp);
JS_ASSERT_IF(ok, vp->isPrimitive());
return ok;
}
@ -120,7 +124,10 @@ JSObject::setGeneric(JSContext *cx, jsid id, js::Value *vp, JSBool strict)
{
if (getOps()->setGeneric)
return nonNativeSetProperty(cx, id, vp, strict);
return js_SetPropertyHelper(cx, this, id, 0, vp, strict);
return js_SetPropertyHelper(cx,
js::RootedVarObject(cx, this),
js::RootedVarId(cx, id),
0, vp, strict);
}
inline JSBool
@ -134,7 +141,7 @@ JSObject::setElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict
{
if (getOps()->setElement)
return nonNativeSetElement(cx, index, vp, strict);
return js_SetElementHelper(cx, this, index, 0, vp, strict);
return js_SetElementHelper(cx, js::RootedVarObject(cx, this), index, 0, vp, strict);
}
inline JSBool
@ -184,7 +191,7 @@ JSObject::getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp)
if (!op(cx, this, receiver, id, vp))
return false;
} else {
if (!js_GetProperty(cx, this, receiver, id, vp))
if (!js_GetProperty(cx, js::RootedVarObject(cx, this), js::RootedVarObject(cx, receiver), id, vp))
return false;
}
return true;
@ -1535,11 +1542,11 @@ FindClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey, JSObject
* avoid losing creation site information for objects made by scripted 'new'.
*/
JSObject *
NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc::AllocKind kind);
NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind kind);
/* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
static inline JSObject *
CopyInitializerObject(JSContext *cx, JSObject *baseobj)
CopyInitializerObject(JSContext *cx, HandleObject baseobj)
{
JS_ASSERT(baseobj->getClass() == &ObjectClass);
JS_ASSERT(!baseobj->inDictionaryMode());
@ -1561,7 +1568,7 @@ CopyInitializerObject(JSContext *cx, JSObject *baseobj)
}
JSObject *
NewReshapedObject(JSContext *cx, js::types::TypeObject *type, JSObject *parent,
NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
gc::AllocKind kind, const Shape *shape);
/*
@ -1733,12 +1740,6 @@ js_InitClass(JSContext *cx, js::HandleObject obj, JSObject *parent_proto,
JSObject **ctorp = NULL,
js::gc::AllocKind ctorKind = JSFunction::FinalizeKind);
inline JSObject *
js_GetProtoIfDenseArray(JSObject *obj)
{
return obj->isDenseArray() ? obj->getProto() : obj;
}
/*
* js_PurgeScopeChain does nothing if obj is not itself a prototype or parent
* scope, else it reshapes the scope and prototype chains it links. It calls

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

@ -312,7 +312,7 @@ PreprocessValue(JSContext *cx, JSObject *holder, KeyType key, Value *vp, Stringi
if (vp->isObject()) {
Value toJSON;
jsid id = ATOM_TO_JSID(cx->runtime->atomState.toJSONAtom);
if (!js_GetMethod(cx, &vp->toObject(), id, 0, &toJSON))
if (!js_GetMethod(cx, RootedVarObject(cx, &vp->toObject()), id, 0, &toJSON))
return false;
if (js_IsCallable(toJSON)) {
@ -745,7 +745,7 @@ js_Stringify(JSContext *cx, Value *vp, JSObject *replacer, Value space, StringBu
}
/* Step 9. */
JSObject *wrapper = NewBuiltinClassInstance(cx, &ObjectClass);
RootedVarObject wrapper(cx, NewBuiltinClassInstance(cx, &ObjectClass));
if (!wrapper)
return false;
@ -783,7 +783,7 @@ Walk(JSContext *cx, JSObject *holder, jsid name, const Value &reviver, Value *vp
/* Step 2. */
if (val.isObject()) {
JSObject *obj = &val.toObject();
RootedVarObject obj(cx, &val.toObject());
/* 'val' must have been produced by the JSON parser, so not a proxy. */
JS_ASSERT(!obj->isProxy());

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

@ -539,7 +539,8 @@ JSONParser::parse(Value *vp)
* js_CheckForStringIndex.
*/
jsid propid = ATOM_TO_JSID(&valueStack.popCopy().toString()->asAtom());
if (!DefineNativeProperty(cx, &valueStack.back().toObject(), propid, v,
RootedVarObject obj(cx, &valueStack.back().toObject());
if (!DefineNativeProperty(cx, obj, propid, v,
JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE,
0, 0))
{

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

@ -54,15 +54,6 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, unsigned scopeIndex, JSObject
JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
JS_ASSERT(!cx->runtime->gcRunning);
/*
* Check for fill from js_SetPropertyHelper where the setter removed shape
* from pobj (via unwatch or delete, e.g.).
*/
if (!pobj->nativeContains(cx, *shape)) {
PCMETER(oddfills++);
return JS_NO_PROP_CACHE_FILL;
}
/*
* Check for overdeep scope and prototype chain. Because resolve, getter,
* and setter hooks can change the prototype chain using JS_SetPrototype

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

@ -270,8 +270,10 @@ ProxyHandler::keys(JSContext *cx, JSObject *proxy, AutoIdVector &props)
}
bool
ProxyHandler::iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp)
ProxyHandler::iterate(JSContext *cx, JSObject *proxy_, unsigned flags, Value *vp)
{
RootedVarObject proxy(cx, proxy_);
JS_ASSERT(OperationInProgress(cx, proxy));
AutoIdVector props(cx);
if ((flags & JSITER_OWNONLY)
@ -318,7 +320,7 @@ ProxyHandler::regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g)
bool
ProxyHandler::defaultValue(JSContext *cx, JSObject *proxy, JSType hint, Value *vp)
{
return DefaultValue(cx, proxy, hint, vp);
return DefaultValue(cx, RootedVarObject(cx, proxy), hint, vp);
}
bool
@ -1756,7 +1758,8 @@ FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp)
* number of fixed slots as the proxy so that we can swap their contents.
*/
gc::AllocKind kind = proxy->getAllocKind();
JSObject *newborn = NewObjectWithGivenProto(cx, clasp, proto, parent, kind);
RootedVarObject newborn(cx);
newborn = NewObjectWithGivenProto(cx, clasp, proto, parent, kind);
if (!newborn)
return false;

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

@ -129,6 +129,7 @@ class RegExpObjectBuilder;
class RegExpShared;
class RegExpStatics;
class MatchPairs;
class PropertyName;
namespace detail { class RegExpCode; }
@ -249,72 +250,23 @@ struct TypeCompartment;
} /* namespace types */
enum ThingRootKind
{
THING_ROOT_OBJECT,
THING_ROOT_SHAPE,
THING_ROOT_BASE_SHAPE,
THING_ROOT_TYPE_OBJECT,
THING_ROOT_STRING,
THING_ROOT_SCRIPT,
THING_ROOT_ID,
THING_ROOT_VALUE,
THING_ROOT_LIMIT
};
typedef JS::Handle<Shape*> HandleShape;
typedef JS::Handle<BaseShape*> HandleBaseShape;
typedef JS::Handle<types::TypeObject*> HandleTypeObject;
typedef JS::Handle<JSAtom*> HandleAtom;
typedef JS::Handle<PropertyName*> HandlePropertyName;
template <typename T> class Root;
template <typename T> class RootedVar;
typedef JS::Root<Shape*> RootShape;
typedef JS::Root<BaseShape*> RootBaseShape;
typedef JS::Root<types::TypeObject*> RootTypeObject;
typedef JS::Root<JSAtom*> RootAtom;
typedef JS::Root<PropertyName*> RootPropertyName;
template <typename T>
struct RootMethods { };
/*
* Reference to a stack location rooted for GC. See "Moving GC Stack Rooting"
* comment in jscntxt.h.
*/
template <typename T>
class Handle
{
public:
/* Copy handles of different types, with implicit coercion. */
template <typename S> Handle(Handle<S> handle) {
testAssign<S>();
ptr = reinterpret_cast<const T *>(handle.address());
}
/* Get a handle from a rooted stack location, with implicit coercion. */
template <typename S> inline Handle(const Root<S> &root);
template <typename S> inline Handle(const RootedVar<S> &root);
const T *address() { return ptr; }
operator T () { return value(); }
T operator ->() { return value(); }
private:
const T *ptr;
T value() { return *ptr; }
template <typename S>
void testAssign() {
#ifdef DEBUG
T a = RootMethods<T>::initial();
S b = RootMethods<S>::initial();
a = b;
(void)a;
#endif
}
};
typedef Handle<JSObject*> HandleObject;
typedef Handle<JSFunction*> HandleFunction;
typedef Handle<Shape*> HandleShape;
typedef Handle<BaseShape*> HandleBaseShape;
typedef Handle<types::TypeObject*> HandleTypeObject;
typedef Handle<JSString*> HandleString;
typedef Handle<JSAtom*> HandleAtom;
typedef Handle<jsid> HandleId;
typedef Handle<Value> HandleValue;
typedef JS::RootedVar<Shape*> RootedVarShape;
typedef JS::RootedVar<BaseShape*> RootedVarBaseShape;
typedef JS::RootedVar<types::TypeObject*> RootedVarTypeObject;
typedef JS::RootedVar<JSAtom*> RootedVarAtom;
typedef JS::RootedVar<PropertyName*> RootedVarPropertyName;
enum XDRMode {
XDR_ENCODE,

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

@ -244,4 +244,67 @@ typedef JSBool (*JSInitCallback)(void);
JS_END_EXTERN_C
#ifdef __cplusplus
namespace JS {
template <typename T>
class Root;
class SkipRoot;
enum ThingRootKind
{
THING_ROOT_OBJECT,
THING_ROOT_SHAPE,
THING_ROOT_BASE_SHAPE,
THING_ROOT_TYPE_OBJECT,
THING_ROOT_STRING,
THING_ROOT_SCRIPT,
THING_ROOT_ID,
THING_ROOT_VALUE,
THING_ROOT_LIMIT
};
struct ContextFriendFields {
JSRuntime *const runtime;
ContextFriendFields(JSRuntime *rt)
: runtime(rt) { }
static const ContextFriendFields *get(const JSContext *cx) {
return reinterpret_cast<const ContextFriendFields *>(cx);
}
static ContextFriendFields *get(JSContext *cx) {
return reinterpret_cast<ContextFriendFields *>(cx);
}
#ifdef JSGC_ROOT_ANALYSIS
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.
*/
Root<void*> *thingGCRooters[THING_ROOT_LIMIT];
#ifdef DEBUG
/*
* Stack allocated list of stack locations which hold non-relocatable
* GC heap pointers (where the target is rooted somewhere else) or integer
* values which may be confused for GC heap pointers. These are used to
* suppress false positives which occur when a rooting analysis treats the
* location as holding a relocatable pointer, but have no other effect on
* GC behavior.
*/
SkipRoot *skipGCRooters;
#endif
#endif /* JSGC_ROOT_ANALYSIS */
};
} /* namespace JS */
#endif /* __cplusplus */
#endif /* jspubtd_h___ */

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

@ -179,7 +179,9 @@ class NodeBuilder
: cx(c), saveLoc(l), src(s) {
}
bool init(JSObject *userobj = NULL) {
bool init(JSObject *userobj_ = NULL) {
RootedVarObject userobj(cx, userobj_);
if (src) {
if (!atomValue(src, &srcval))
return false;
@ -202,7 +204,10 @@ class NodeBuilder
const char *name = callbackNames[i];
JSAtom *atom = js_Atomize(cx, name, strlen(name));
if (!atom || !GetPropertyDefault(cx, userobj, ATOM_TO_JSID(atom), NullValue(), &funv))
if (!atom)
return false;
RootedVarId id(cx, ATOM_TO_JSID(atom));
if (!GetPropertyDefault(cx, userobj, id, NullValue(), &funv))
return false;
if (funv.isNullOrUndefined()) {
@ -3123,24 +3128,22 @@ reflect_parse(JSContext *cx, uint32_t argc, jsval *vp)
return JS_FALSE;
}
JSObject *config = &arg.toObject();
RootedVarObject config(cx, &arg.toObject());
Value prop;
/* config.loc */
if (!GetPropertyDefault(cx, config, ATOM_TO_JSID(cx->runtime->atomState.locAtom),
BooleanValue(true), &prop)) {
RootedVarId locId(cx, ATOM_TO_JSID(cx->runtime->atomState.locAtom));
if (!GetPropertyDefault(cx, config, locId, BooleanValue(true), &prop))
return JS_FALSE;
}
loc = js_ValueToBoolean(prop);
if (loc) {
/* config.source */
if (!GetPropertyDefault(cx, config, ATOM_TO_JSID(cx->runtime->atomState.sourceAtom),
NullValue(), &prop)) {
RootedVarId sourceId(cx, ATOM_TO_JSID(cx->runtime->atomState.sourceAtom));
if (!GetPropertyDefault(cx, config, sourceId, NullValue(), &prop))
return JS_FALSE;
}
if (!prop.isNullOrUndefined()) {
JSString *str = ToString(cx, prop);
@ -3159,18 +3162,17 @@ reflect_parse(JSContext *cx, uint32_t argc, jsval *vp)
}
/* config.line */
if (!GetPropertyDefault(cx, config, ATOM_TO_JSID(cx->runtime->atomState.lineAtom),
Int32Value(1), &prop) ||
RootedVarId lineId(cx, ATOM_TO_JSID(cx->runtime->atomState.lineAtom));
if (!GetPropertyDefault(cx, config, lineId, Int32Value(1), &prop) ||
!ToUint32(cx, prop, &lineno)) {
return JS_FALSE;
}
}
/* config.builder */
if (!GetPropertyDefault(cx, config, ATOM_TO_JSID(cx->runtime->atomState.builderAtom),
NullValue(), &prop)) {
RootedVarId builderId(cx, ATOM_TO_JSID(cx->runtime->atomState.builderAtom));
if (!GetPropertyDefault(cx, config, builderId, NullValue(), &prop))
return JS_FALSE;
}
if (!prop.isNullOrUndefined()) {
if (!prop.isObject()) {

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

@ -312,7 +312,7 @@ Shape::getChildBinding(JSContext *cx, const StackShape &child)
Shape *shape = JS_PROPERTY_TREE(cx).getChild(cx, this, numFixedSlots(), child);
if (shape) {
JS_ASSERT(shape->parent == this);
//JS_ASSERT(shape->parent == this); // XXX 'this' is not rooted here
/*
* Update the number of fixed slots which bindings of this shape will
@ -520,12 +520,14 @@ JSObject::addProperty(JSContext *cx, jsid id,
NormalizeGetterAndSetter(cx, this, id, attrs, flags, getter, setter);
RootedVarObject self(cx, this);
Shape **spp = NULL;
if (inDictionaryMode())
spp = lastProperty()->table().search(id, true);
return addPropertyInternal(cx, id, getter, setter, slot, attrs, flags, shortid,
spp, allowDictionary);
return self->addPropertyInternal(cx, id, getter, setter, slot, attrs, flags, shortid,
spp, allowDictionary);
}
Shape *
@ -551,7 +553,7 @@ JSObject::addPropertyInternal(JSContext *cx, jsid id,
(!stableSlot || lastProperty()->entryCount() >= PropertyTree::MAX_HEIGHT)) {
if (!toDictionaryMode(cx))
return NULL;
table = &lastProperty()->table();
table = &self->lastProperty()->table();
spp = table->search(id, true);
}
} else {
@ -995,7 +997,7 @@ JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *n
RootShape newRoot(cx, &newShape);
if (!toDictionaryMode(cx))
return NULL;
oldShape = lastProperty();
oldShape = self->lastProperty();
}
if (!newShape) {
@ -1022,7 +1024,7 @@ JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *n
JS_ASSERT(newShape->parent == oldShape);
oldShape->removeFromDictionary(self);
if (newShape == lastProperty())
if (newShape == self->lastProperty())
oldShape->handoffTableTo(newShape);
if (spp)
@ -1269,7 +1271,7 @@ Bindings::setParent(JSContext *cx, JSObject *obj)
* mark the stack value as non-relocatable for the stack root analysis.
*/
Bindings *self = this;
CheckRoot root(cx, &self);
SkipRoot root(cx, &self);
RootObject rootObj(cx, &obj);
@ -1320,6 +1322,9 @@ EmptyShape::getInitialShape(JSContext *cx, Class *clasp, JSObject *proto, JSObje
if (p)
return p->shape;
RootObject protoRoot(cx, &lookup.proto);
RootObject parentRoot(cx, &lookup.parent);
RootedVar<UnownedBaseShape*> nbase(cx);
StackBaseShape base(clasp, parent, objectFlags);
@ -1334,7 +1339,7 @@ EmptyShape::getInitialShape(JSContext *cx, Class *clasp, JSObject *proto, JSObje
InitialShapeEntry entry;
entry.shape = shape;
entry.proto = proto;
entry.proto = lookup.proto;
if (!table.relookupOrAdd(p, lookup, entry))
return NULL;

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

@ -519,6 +519,10 @@ struct Shape : public js::gc::Cell
static inline Shape *search(JSContext *cx, Shape *start, jsid id,
Shape ***pspp, bool adding = false);
#ifdef DEBUG
static inline Shape *searchNoAllocation(JSContext *cx, Shape *start, jsid id);
#endif
inline void removeFromDictionary(JSObject *obj);
inline void insertIntoDictionary(HeapPtrShape *dictp);
@ -1079,6 +1083,24 @@ Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
return NULL;
}
#ifdef DEBUG
/* static */ inline Shape *
Shape::searchNoAllocation(JSContext *cx, Shape *start, jsid id)
{
if (start->hasTable()) {
Shape **spp = start->table().search(id, false);
return SHAPE_FETCH(spp);
}
for (Shape *shape = start; shape; shape = shape->parent) {
if (shape->propidRef() == id)
return shape;
}
return NULL;
}
#endif /* DEBUG */
} // namespace js
#ifdef _MSC_VER

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

@ -103,7 +103,7 @@ Bindings::lookup(JSContext *cx, JSAtom *name, unsigned *indexp) const
}
bool
Bindings::add(JSContext *cx, JSAtom *name, BindingKind kind)
Bindings::add(JSContext *cx, HandleAtom name, BindingKind kind)
{
if (!ensureShape(cx))
return false;
@ -492,10 +492,10 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
continue;
}
JSAtom *name;
RootedVarAtom name(cx);
if (mode == XDR_ENCODE)
name = names[i];
if (!XDRAtom(xdr, &name))
if (!XDRAtom(xdr, name.address()))
return false;
if (mode == XDR_DECODE) {
BindingKind kind = (i < nargs)

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

@ -194,23 +194,23 @@ class Bindings
* runtime, by calling an "add" method. All ARGUMENT bindings must be added
* before before any VARIABLE or CONSTANT bindings.
*/
bool add(JSContext *cx, JSAtom *name, BindingKind kind);
bool add(JSContext *cx, HandleAtom name, BindingKind kind);
/* Convenience specializations. */
bool addVariable(JSContext *cx, JSAtom *name) {
bool addVariable(JSContext *cx, HandleAtom name) {
return add(cx, name, VARIABLE);
}
bool addConstant(JSContext *cx, JSAtom *name) {
bool addConstant(JSContext *cx, HandleAtom name) {
return add(cx, name, CONSTANT);
}
bool addArgument(JSContext *cx, JSAtom *name, uint16_t *slotp) {
bool addArgument(JSContext *cx, HandleAtom name, uint16_t *slotp) {
JS_ASSERT(name != NULL); /* not destructuring */
*slotp = nargs;
return add(cx, name, ARGUMENT);
}
bool addDestructuring(JSContext *cx, uint16_t *slotp) {
*slotp = nargs;
return add(cx, NULL, ARGUMENT);
return add(cx, RootedVarAtom(cx), ARGUMENT);
}
void noteDup() { hasDup_ = true; }

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

@ -468,11 +468,11 @@ ThisToStringForStringProto(JSContext *cx, CallReceiver call)
return call.thisv().toString();
if (call.thisv().isObject()) {
JSObject *obj = &call.thisv().toObject();
RootedVarObject obj(cx, &call.thisv().toObject());
if (obj->isString() &&
ClassMethodIsNative(cx, obj,
&StringClass,
ATOM_TO_JSID(cx->runtime->atomState.toStringAtom),
RootedVarId(cx, ATOM_TO_JSID(cx->runtime->atomState.toStringAtom)),
js_str_toString))
{
JSString *str = obj->asString().unbox();
@ -1497,7 +1497,7 @@ class StringRegExpGuard
return true;
/* Build RegExp from pattern string. */
JSString *opt;
RootedVarString opt(cx);
if (optarg < args.length()) {
opt = ToString(cx, args[optarg]);
if (!opt)
@ -1550,19 +1550,20 @@ static bool
DoMatch(JSContext *cx, RegExpStatics *res, JSString *str, RegExpShared &re,
DoMatchCallback callback, void *data, MatchControlFlags flags, Value *rval)
{
JSLinearString *linearStr = str->ensureLinear(cx);
RootedVar<JSLinearString*> linearStr(cx, str->ensureLinear(cx));
if (!linearStr)
return false;
const jschar *chars = linearStr->chars();
size_t length = linearStr->length();
if (re.global()) {
RegExpExecType type = (flags & TEST_GLOBAL_BIT) ? RegExpTest : RegExpExec;
for (size_t count = 0, i = 0, length = str->length(); i <= length; ++count) {
if (!JS_CHECK_OPERATION_LIMIT(cx))
return false;
if (!ExecuteRegExp(cx, res, re, linearStr, chars, length, &i, type, rval))
const jschar *chars = linearStr->chars();
size_t charsLen = linearStr->length();
if (!ExecuteRegExp(cx, res, re, linearStr, chars, charsLen, &i, type, rval))
return false;
if (!Matched(type, *rval))
break;
@ -1572,10 +1573,13 @@ DoMatch(JSContext *cx, RegExpStatics *res, JSString *str, RegExpShared &re,
++i;
}
} else {
const jschar *chars = linearStr->chars();
size_t charsLen = linearStr->length();
RegExpExecType type = (flags & TEST_SINGLE_BIT) ? RegExpTest : RegExpExec;
bool callbackOnSingle = !!(flags & CALLBACK_ON_SINGLE_BIT);
size_t i = 0;
if (!ExecuteRegExp(cx, res, re, linearStr, chars, length, &i, type, rval))
if (!ExecuteRegExp(cx, res, re, linearStr, chars, charsLen, &i, type, rval))
return false;
if (callbackOnSingle && Matched(type, *rval) && !callback(cx, res, 0, data))
return false;
@ -1651,8 +1655,8 @@ js::str_match(JSContext *cx, unsigned argc, Value *vp)
if (!g.normalizeRegExp(cx, false, 1, args))
return false;
JSObject *array = NULL;
MatchArgType arg = &array;
RootedVarObject array(cx);
MatchArgType arg = array.address();
RegExpStatics *res = cx->regExpStatics();
Value rval;
if (!DoMatch(cx, res, str, g.regExp(), MatchCallback, arg, MATCH_ARGS, &rval))
@ -1711,14 +1715,14 @@ js::str_search(JSContext *cx, unsigned argc, Value *vp)
struct ReplaceData
{
ReplaceData(JSContext *cx)
: sb(cx)
: str(cx), lambda(cx), elembase(cx), repstr(cx), sb(cx)
{}
JSString *str; /* 'this' parameter object as a string */
RootedVarString str; /* 'this' parameter object as a string */
StringRegExpGuard g; /* regexp parameter object and private data */
JSObject *lambda; /* replacement function object or null */
JSObject *elembase; /* object for function(a){return b[a]} replace */
JSLinearString *repstr; /* replacement string */
RootedVarObject lambda; /* replacement function object or null */
RootedVarObject elembase; /* object for function(a){return b[a]} replace */
RootedVar<JSLinearString*> repstr; /* replacement string */
const jschar *dollar; /* null or pointer to first $ in repstr */
const jschar *dollarEnd; /* limit pointer for js_strchr_limit */
int leftIndex; /* left context index in str->chars */
@ -1795,7 +1799,8 @@ InterpretDollar(JSContext *cx, RegExpStatics *res, const jschar *dp, const jscha
static bool
FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t *sizep)
{
if (JSObject *base = rdata.elembase) {
RootedVarObject base(cx, rdata.elembase);
if (base) {
/*
* The base object is used when replace was passed a lambda which looks like
* 'function(a) { return b[a]; }' for the base object b. b will not change
@ -1943,9 +1948,7 @@ ReplaceRegExpCallback(JSContext *cx, RegExpStatics *res, size_t count, void *p)
ReplaceData &rdata = *static_cast<ReplaceData *>(p);
rdata.calledBack = true;
JSLinearString &str = rdata.str->asLinear(); /* flattened for regexp */
size_t leftoff = rdata.leftIndex;
const jschar *left = str.chars() + leftoff;
size_t leftlen = res->matchStart() - leftoff;
rdata.leftIndex = res->matchLimit();
@ -1956,13 +1959,17 @@ ReplaceRegExpCallback(JSContext *cx, RegExpStatics *res, size_t count, void *p)
size_t growth = leftlen + replen;
if (!rdata.sb.reserve(rdata.sb.length() + growth))
return false;
JSLinearString &str = rdata.str->asLinear(); /* flattened for regexp */
const jschar *left = str.chars() + leftoff;
rdata.sb.infallibleAppend(left, leftlen); /* skipped-over portion of the search value */
DoReplace(cx, res, rdata);
return true;
}
static bool
BuildFlatReplacement(JSContext *cx, JSString *textstr, JSString *repstr,
BuildFlatReplacement(JSContext *cx, HandleString textstr, HandleString repstr,
const FlatMatch &fm, CallArgs *args)
{
RopeBuilder builder(cx);
@ -1994,7 +2001,8 @@ BuildFlatReplacement(JSContext *cx, JSString *textstr, JSString *repstr,
* the first character in the pattern, so we include the
* replacement string here.
*/
JSString *leftSide = js_NewDependentString(cx, str, 0, match - pos);
RootedVarString leftSide(cx);
leftSide = js_NewDependentString(cx, str, 0, match - pos);
if (!leftSide ||
!builder.append(leftSide) ||
!builder.append(repstr)) {
@ -2007,13 +2015,14 @@ BuildFlatReplacement(JSContext *cx, JSString *textstr, JSString *repstr,
* last part of str.
*/
if (strEnd > matchEnd) {
JSString *rightSide = js_NewDependentString(cx, str, matchEnd - pos,
strEnd - matchEnd);
RootedVarString rightSide(cx);
rightSide = js_NewDependentString(cx, str, matchEnd - pos,
strEnd - matchEnd);
if (!rightSide || !builder.append(rightSide))
return false;
}
} else {
if (!builder.append(str))
if (!builder.append(RootedVarString(cx, str)))
return false;
}
pos += str->length();
@ -2021,11 +2030,13 @@ BuildFlatReplacement(JSContext *cx, JSString *textstr, JSString *repstr,
return false;
}
} else {
JSString *leftSide = js_NewDependentString(cx, textstr, 0, match);
RootedVarString leftSide(cx);
leftSide = js_NewDependentString(cx, textstr, 0, match);
if (!leftSide)
return false;
JSString *rightSide = js_NewDependentString(cx, textstr, match + fm.patternLength(),
textstr->length() - match - fm.patternLength());
RootedVarString rightSide(cx);
rightSide = js_NewDependentString(cx, textstr, match + fm.patternLength(),
textstr->length() - match - fm.patternLength());
if (!rightSide ||
!builder.append(leftSide) ||
!builder.append(repstr) ||
@ -2101,15 +2112,15 @@ BuildDollarReplacement(JSContext *cx, JSString *textstrArg, JSLinearString *reps
++it; /* We always eat an extra char in the above switch. */
}
JSString *leftSide = js_NewDependentString(cx, textstr, 0, matchStart);
RootedVarString leftSide(cx, js_NewDependentString(cx, textstr, 0, matchStart));
ENSURE(leftSide);
JSString *newReplace = newReplaceChars.finishString();
RootedVarString newReplace(cx, newReplaceChars.finishString());
ENSURE(newReplace);
JS_ASSERT(textstr->length() >= matchLimit);
JSString *rightSide = js_NewDependentString(cx, textstr, matchLimit,
textstr->length() - matchLimit);
RootedVarString rightSide(cx, js_NewDependentString(cx, textstr, matchLimit,
textstr->length() - matchLimit));
ENSURE(rightSide);
RopeBuilder builder(cx);
@ -2183,17 +2194,17 @@ str_replace_flat_lambda(JSContext *cx, CallArgs outerArgs, ReplaceData &rdata, c
if (!Invoke(cx, rdata.args))
return false;
JSString *repstr = ToString(cx, args.rval());
RootedVarString repstr(cx, ToString(cx, args.rval()));
if (!repstr)
return false;
JSString *leftSide = js_NewDependentString(cx, rdata.str, 0, fm.match());
RootedVarString leftSide(cx, js_NewDependentString(cx, rdata.str, 0, fm.match()));
if (!leftSide)
return false;
size_t matchLimit = fm.match() + fm.patternLength();
JSString *rightSide = js_NewDependentString(cx, rdata.str, matchLimit,
rdata.str->length() - matchLimit);
RootedVarString rightSide(cx, js_NewDependentString(cx, rdata.str, matchLimit,
rdata.str->length() - matchLimit));
if (!rightSide)
return false;
@ -2382,7 +2393,7 @@ class SplitMatchResult {
template<class Matcher>
static JSObject *
SplitHelper(JSContext *cx, JSLinearString *str, uint32_t limit, Matcher splitMatch, TypeObject *type)
SplitHelper(JSContext *cx, Handle<JSLinearString*> str, uint32_t limit, Matcher splitMatch, TypeObject *type)
{
size_t strLength = str->length();
SplitMatchResult result;
@ -2405,8 +2416,8 @@ SplitHelper(JSContext *cx, JSLinearString *str, uint32_t limit, Matcher splitMat
if (!result.isFailure())
return NewDenseEmptyArray(cx);
Value v = StringValue(str);
return NewDenseCopiedArray(cx, 1, &v);
RootedVarValue v(cx, StringValue(str));
return NewDenseCopiedArray(cx, 1, v.address());
}
/* Step 12. */
@ -2544,14 +2555,12 @@ class SplitRegExpMatcher
class SplitStringMatcher
{
const jschar *sepChars;
size_t sepLength;
RootedVar<JSLinearString*> sep;
public:
SplitStringMatcher(JSLinearString *sep) {
sepChars = sep->chars();
sepLength = sep->length();
}
SplitStringMatcher(JSContext *cx, JSLinearString *sep)
: sep(cx, sep)
{}
static const bool returnsCaptures = false;
@ -2559,11 +2568,12 @@ class SplitStringMatcher
{
JS_ASSERT(index == 0 || index < str->length());
const jschar *chars = str->chars();
int match = StringMatch(chars + index, str->length() - index, sepChars, sepLength);
int match = StringMatch(chars + index, str->length() - index,
sep->chars(), sep->length());
if (match == -1)
res->setFailure();
else
res->setResult(sepLength, index + match + sepLength);
res->setResult(sep->length(), index + match + sep->length());
return true;
}
};
@ -2579,7 +2589,7 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp)
if (!str)
return false;
TypeObject *type = GetTypeCallerInitObject(cx, JSProto_Array);
RootedVarTypeObject type(cx, GetTypeCallerInitObject(cx, JSProto_Array));
if (!type)
return false;
AddTypeProperty(cx, type, NULL, Type::StringType());
@ -2630,14 +2640,14 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp)
args.rval() = ObjectValue(*aobj);
return true;
}
JSLinearString *strlin = str->ensureLinear(cx);
RootedVar<JSLinearString*> strlin(cx, str->ensureLinear(cx));
if (!strlin)
return false;
/* Steps 11-15. */
JSObject *aobj;
if (!re.initialized())
aobj = SplitHelper(cx, strlin, limit, SplitStringMatcher(sepstr), type);
aobj = SplitHelper(cx, strlin, limit, SplitStringMatcher(cx, sepstr), type);
else
aobj = SplitHelper(cx, strlin, limit, SplitRegExpMatcher(*re, cx->regExpStatics()), type);
if (!aobj)
@ -2705,12 +2715,12 @@ static JSBool
str_concat(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSString *str = ThisToStringForStringProto(cx, args);
RootedVarString str(cx, ThisToStringForStringProto(cx, args));
if (!str)
return false;
for (unsigned i = 0; i < args.length(); i++) {
JSString *argStr = ToString(cx, args[i]);
RootedVarString argStr(cx, ToString(cx, args[i]));
if (!argStr)
return false;
@ -3012,7 +3022,7 @@ js_String(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSString *str;
RootedVarString str(cx);
if (args.length() > 0) {
str = ToString(cx, args[0]);
if (!str)
@ -3090,14 +3100,15 @@ js_InitStringClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = &obj->asGlobal();
RootedVar<GlobalObject*> global(cx, &obj->asGlobal());
JSObject *proto = global->createBlankPrototype(cx, &StringClass);
if (!proto || !proto->asString().init(cx, cx->runtime->emptyString))
RootedVarObject proto(cx, global->createBlankPrototype(cx, &StringClass));
if (!proto || !proto->asString().init(cx, RootedVarString(cx, cx->runtime->emptyString)))
return NULL;
/* Now create the String function. */
JSFunction *ctor = global->createConstructor(cx, js_String, CLASS_ATOM(cx, String), 1);
RootedVarFunction ctor(cx);
ctor = global->createConstructor(cx, js_String, CLASS_ATOM(cx, String), 1);
if (!ctor)
return NULL;
@ -3312,7 +3323,7 @@ js_ValueToSource(JSContext *cx, const Value &v)
Value rval = NullValue();
Value fval;
jsid id = ATOM_TO_JSID(cx->runtime->atomState.toSourceAtom);
if (!js_GetMethod(cx, &v.toObject(), id, 0, &fval))
if (!js_GetMethod(cx, RootedVarObject(cx, &v.toObject()), id, 0, &fval))
return NULL;
if (js_IsCallable(fval)) {
if (!Invoke(cx, v, fval, 0, NULL, &rval))

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

@ -74,7 +74,7 @@ class RopeBuilder;
} /* namespace js */
extern JSString * JS_FASTCALL
js_ConcatStrings(JSContext *cx, JSString *s1, JSString *s2);
js_ConcatStrings(JSContext *cx, js::HandleString s1, js::HandleString s2);
extern JSString * JS_FASTCALL
js_toLowerCase(JSContext *cx, JSString *str);

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

@ -53,17 +53,17 @@ namespace js {
class RopeBuilder {
JSContext *cx;
JSString *res;
RootedVarString res;
RopeBuilder(const RopeBuilder &other) MOZ_DELETE;
void operator=(const RopeBuilder &other) MOZ_DELETE;
public:
RopeBuilder(JSContext *cx)
: cx(cx), res(cx->runtime->emptyString)
: cx(cx), res(cx, cx->runtime->emptyString)
{}
inline bool append(JSString *str) {
inline bool append(HandleString str) {
res = js_ConcatStrings(cx, res, str);
return !!res;
}

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

@ -473,10 +473,10 @@ ArrayBuffer::obj_getGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, js
return true;
}
JSObject *delegate = DelegateObject(cx, obj);
RootedVarObject delegate(cx, DelegateObject(cx, obj));
if (!delegate)
return false;
return js_GetProperty(cx, delegate, receiver, id, vp);
return js_GetProperty(cx, delegate, RootedVarObject(cx, receiver), id, vp);
}
JSBool
@ -489,19 +489,19 @@ ArrayBuffer::obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, P
return true;
}
JSObject *delegate = DelegateObject(cx, obj);
RootedVarObject delegate(cx, DelegateObject(cx, obj));
if (!delegate)
return false;
return js_GetProperty(cx, delegate, receiver, ATOM_TO_JSID(name), vp);
return js_GetProperty(cx, delegate, RootedVarObject(cx, receiver), ATOM_TO_JSID(name), vp);
}
JSBool
ArrayBuffer::obj_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp)
{
JSObject *delegate = DelegateObject(cx, getArrayBuffer(obj));
RootedVarObject delegate(cx, DelegateObject(cx, getArrayBuffer(obj)));
if (!delegate)
return false;
return js_GetElement(cx, delegate, receiver, index, vp);
return js_GetElement(cx, delegate, RootedVarObject(cx, receiver), index, vp);
}
JSBool
@ -526,6 +526,10 @@ ArrayBuffer::obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JS
if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom))
return true;
RootedVarObject delegate(cx, DelegateObject(cx, obj));
if (!delegate)
return false;
if (JSID_IS_ATOM(id, cx->runtime->atomState.protoAtom)) {
// setting __proto__ = null
// effectively removes the prototype chain.
@ -545,9 +549,6 @@ ArrayBuffer::obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JS
// and we don't modify our prototype chain
// since obj_getProperty will fetch it as a plain
// property from the delegate.
JSObject *delegate = DelegateObject(cx, obj);
if (!delegate)
return false;
JSObject *oldDelegateProto = delegate->getProto();
@ -571,10 +572,6 @@ ArrayBuffer::obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JS
return true;
}
JSObject *delegate = DelegateObject(cx, obj);
if (!delegate)
return false;
return js_SetPropertyHelper(cx, delegate, id, 0, vp, strict);
}
@ -587,7 +584,7 @@ ArrayBuffer::obj_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, V
JSBool
ArrayBuffer::obj_setElement(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict)
{
JSObject *delegate = DelegateObject(cx, obj);
RootedVarObject delegate(cx, DelegateObject(cx, obj));
if (!delegate)
return false;

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

@ -265,7 +265,7 @@ Wrapper::iterate(JSContext *cx, JSObject *wrapper, unsigned flags, Value *vp)
{
vp->setUndefined(); // default result if we refuse to perform this action
const jsid id = JSID_VOID;
GET(GetIterator(cx, wrappedObject(wrapper), flags, vp));
GET(GetIterator(cx, RootedVarObject(cx, wrappedObject(wrapper)), flags, vp));
}
bool
@ -366,7 +366,7 @@ Wrapper::defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp)
bool
Wrapper::iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp)
{
if (!js_IteratorMore(cx, wrappedObject(wrapper), vp))
if (!js_IteratorMore(cx, RootedVarObject(cx, wrappedObject(wrapper)), vp))
return false;
if (vp->toBoolean()) {
@ -692,8 +692,8 @@ Reify(JSContext *cx, JSCompartment *origin, Value *vp)
AutoCloseIterator close(cx, iterObj);
/* Wrap the iteratee. */
JSObject *obj = ni->obj;
if (!origin->wrap(cx, &obj))
RootedVarObject obj(cx, ni->obj);
if (!origin->wrap(cx, obj.address()))
return false;
/*

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

@ -156,7 +156,7 @@ const char js_leftcurly_entity_str[] = "&#123;";
#define IS_STAR(str) ((str)->length() == 1 && *(str)->chars() == '*')
static JSBool
GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
GetXMLFunction(JSContext *cx, HandleObject obj, HandleId id, jsval *vp);
static JSBool
IsDeclared(const JSObject *obj)
@ -405,8 +405,8 @@ static JSString *
ConvertQNameToString(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isQName());
JSString *uri = obj->getNameURI();
JSString *str;
RootedVarString uri(cx, obj->getNameURI());
RootedVarString str(cx);
if (!uri) {
/* No uri means wildcard qualifier. */
str = cx->runtime->atomState.starQualifierAtom;
@ -414,12 +414,12 @@ ConvertQNameToString(JSContext *cx, JSObject *obj)
/* Empty string for uri means localName is in no namespace. */
str = cx->runtime->emptyString;
} else {
JSString *qualstr = cx->runtime->atomState.qualifierAtom;
RootedVarString qualstr(cx, cx->runtime->atomState.qualifierAtom);
str = js_ConcatStrings(cx, uri, qualstr);
if (!str)
return NULL;
}
str = js_ConcatStrings(cx, str, obj->getQNameLocalName());
str = js_ConcatStrings(cx, str, RootedVarString(cx, obj->getQNameLocalName()));
if (!str)
return NULL;
@ -3765,13 +3765,15 @@ GetNamedProperty(JSContext *cx, JSXML *xml, JSObject* nameqn, JSXML *list)
/* ECMA-357 9.1.1.1 XML [[Get]] and 9.2.1.1 XMLList [[Get]]. */
static JSBool
GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
GetProperty(JSContext *cx, JSObject *obj_, jsid id_, jsval *vp)
{
JSXML *xml, *list, *kid;
uint32_t index;
JSObject *kidobj, *listobj;
JSObject *nameqn;
jsid funid;
RootedVarObject obj(cx, obj_);
RootedVarId id(cx, id_);
if (!obj->isXML())
return true;
@ -3811,7 +3813,8 @@ GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
/*
* ECMA-357 9.2.1.1/9.1.1.1 qname case.
*/
nameqn = ToXMLName(cx, IdToJsval(id), &funid);
RootedVarId funid(cx);
nameqn = ToXMLName(cx, IdToJsval(id), funid.address());
if (!nameqn)
return false;
if (!JSID_IS_VOID(funid))
@ -3880,18 +3883,21 @@ ResolveValue(JSContext *cx, JSXML *list, JSXML **result);
/* ECMA-357 9.1.1.2 XML [[Put]] and 9.2.1.2 XMLList [[Put]]. */
static JSBool
PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
PutProperty(JSContext *cx, JSObject *obj_, jsid id_, JSBool strict, jsval *vp)
{
JSBool ok, primitiveAssign;
enum { OBJ_ROOT, ID_ROOT, VAL_ROOT };
JSXML *xml, *vxml, *rxml, *kid, *attr, *parent, *copy, *kid2, *match;
JSObject *vobj, *nameobj, *attrobj, *parentobj, *kidobj, *copyobj;
JSObject *vobj, *nameobj, *attrobj, *kidobj, *copyobj;
JSObject *targetprop, *nameqn, *attrqn;
uint32_t index, i, j, k, n, q, matchIndex;
jsval attrval, nsval;
jsid funid;
JSObject *ns;
RootedVarObject obj(cx, obj_);
RootedVarId id(cx, id_);
if (!obj->isXML())
return JS_TRUE;
xml = (JSXML *) obj->getPrivate();
@ -4094,7 +4100,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
if (parent) {
/* 2(e)(i). */
parentobj = js_GetXMLObject(cx, parent);
RootedVarObject parentobj(cx, js_GetXMLObject(cx, parent));
if (!parentobj)
goto bad;
ok = PutProperty(cx, parentobj, id, strict, vp);
@ -4302,16 +4308,16 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
if (n == 0) {
*vp = STRING_TO_JSVAL(cx->runtime->emptyString);
} else {
JSString *left = KidToString(cx, vxml, 0);
RootedVarString left(cx, KidToString(cx, vxml, 0));
if (!left)
goto bad;
JSString *space = cx->runtime->atomState.spaceAtom;
RootedVarString space(cx, cx->runtime->atomState.spaceAtom);
for (i = 1; i < n; i++) {
left = js_ConcatStrings(cx, left, space);
if (!left)
goto bad;
JSString *right = KidToString(cx, vxml, i);
RootedVarString right(cx, KidToString(cx, vxml, i));
if (!right)
goto bad;
left = js_ConcatStrings(cx, left, right);
@ -4527,7 +4533,6 @@ ResolveValue(JSContext *cx, JSXML *list, JSXML **result)
{
JSXML *target, *base;
JSObject *targetprop;
jsid id;
jsval tv;
if (list->xml_class != JSXML_CLASS_LIST || list->xml_kids.length != 0) {
@ -4558,7 +4563,7 @@ ResolveValue(JSContext *cx, JSXML *list, JSXML **result)
if (!js_GetXMLObject(cx, base))
return JS_FALSE;
id = OBJECT_TO_JSID(targetprop);
RootedVarId id(cx, OBJECT_TO_JSID(targetprop));
if (!GetProperty(cx, base->object, id, &tv))
return JS_FALSE;
target = (JSXML *) JSVAL_TO_OBJECT(tv)->getPrivate();
@ -5212,7 +5217,7 @@ again:
* 11.2.2.1 Step 3(d) onward.
*/
JSBool
js_GetXMLMethod(JSContext *cx, JSObject *obj, jsid id, Value *vp)
js_GetXMLMethod(JSContext *cx, HandleObject obj, jsid id, Value *vp)
{
JS_ASSERT(obj->isXML());
@ -5224,7 +5229,7 @@ js_GetXMLMethod(JSContext *cx, JSObject *obj, jsid id, Value *vp)
* local value as vp, we use a proper root here.
*/
AutoValueRooter tvr(cx);
JSBool ok = GetXMLFunction(cx, obj, id, tvr.addr());
JSBool ok = GetXMLFunction(cx, obj, RootedVarId(cx, id), tvr.addr());
*vp = tvr.value();
return ok;
}
@ -6337,7 +6342,8 @@ xml_normalize_helper(JSContext *cx, JSObject *obj, JSXML *xml)
while (i + 1 < n &&
(kid2 = XMLARRAY_MEMBER(&xml->xml_kids, i + 1, JSXML)) &&
kid2->xml_class == JSXML_CLASS_TEXT) {
str = js_ConcatStrings(cx, kid->xml_value, kid2->xml_value);
str = js_ConcatStrings(cx, RootedVarString(cx, kid->xml_value),
RootedVarString(cx, kid2->xml_value));
if (!str)
return JS_FALSE;
NormalizingDelete(cx, xml, i + 1);
@ -6959,8 +6965,6 @@ xml_text(JSContext *cx, unsigned argc, jsval *vp)
static JSString *
xml_toString_helper(JSContext *cx, JSXML *xml)
{
JSString *str, *kidstr;
if (xml->xml_class == JSXML_CLASS_ATTRIBUTE ||
xml->xml_class == JSXML_CLASS_TEXT) {
return xml->xml_value;
@ -6969,14 +6973,14 @@ xml_toString_helper(JSContext *cx, JSXML *xml)
if (!HasSimpleContent(xml))
return ToXMLString(cx, OBJECT_TO_JSVAL(xml->object), 0);
str = cx->runtime->emptyString;
RootedVarString str(cx, cx->runtime->emptyString);
if (!js_EnterLocalRootScope(cx))
return NULL;
JSXMLArrayCursor<JSXML> cursor(&xml->xml_kids);
while (JSXML *kid = cursor.getNext()) {
if (kid->xml_class != JSXML_CLASS_COMMENT &&
kid->xml_class != JSXML_CLASS_PROCESSING_INSTRUCTION) {
kidstr = xml_toString_helper(cx, kid);
RootedVarString kidstr(cx, xml_toString_helper(cx, kid));
if (!kidstr) {
str = NULL;
break;
@ -7795,7 +7799,7 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *i
}
static JSBool
GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
GetXMLFunction(JSContext *cx, HandleObject obj, HandleId id, jsval *vp)
{
JS_ASSERT(obj->isXML());
@ -7803,7 +7807,7 @@ GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
* See comments before xml_lookupGeneric about the need for the proto
* chain lookup.
*/
JSObject *target = obj;
RootedVarObject target(cx, obj);
for (;;) {
if (!js_GetProperty(cx, target, id, vp))
return false;

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

@ -287,7 +287,7 @@ extern JSBool
js_FindXMLProperty(JSContext *cx, const js::Value &nameval, JSObject **objp, jsid *idp);
extern JSBool
js_GetXMLMethod(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
js_GetXMLMethod(JSContext *cx, js::HandleObject obj, jsid id, js::Value *vp);
extern JSBool
js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp);

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

@ -6535,7 +6535,7 @@ mjit::Compiler::jsop_newinit()
{
bool isArray;
unsigned count = 0;
JSObject *baseobj = NULL;
RootedVarObject baseobj(cx);
switch (*PC) {
case JSOP_NEWINIT:
isArray = (GET_UINT8(PC) == JSProto_Array);
@ -6571,7 +6571,7 @@ mjit::Compiler::jsop_newinit()
* Don't bake in types for non-compileAndGo scripts, or at initializers
* producing objects with singleton types.
*/
types::TypeObject *type = NULL;
RootedVarTypeObject type(cx);
if (globalObj && !types::UseNewTypeForInitializer(cx, script, PC)) {
type = types::TypeScript::InitObject(cx, script, PC,
isArray ? JSProto_Array : JSProto_Object);
@ -7008,7 +7008,7 @@ mjit::Compiler::constructThis()
{
JS_ASSERT(isConstructing);
JSFunction *fun = script->function();
RootedVarFunction fun(cx, script->function());
do {
if (!cx->typeInferenceEnabled() ||

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

@ -641,7 +641,7 @@ stubs::CreateThis(VMFrame &f, JSObject *proto)
{
JSContext *cx = f.cx;
StackFrame *fp = f.fp();
JSObject *callee = &fp->callee();
RootedVarObject callee(cx, &fp->callee());
JSObject *obj = js_CreateThisForFunctionWithProto(cx, callee, proto);
if (!obj)
THROW();
@ -903,7 +903,7 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
break;
case REJOIN_THIS_PROTOTYPE: {
JSObject *callee = &fp->callee();
RootedVarObject callee(cx, &fp->callee());
JSObject *proto = f.regs.sp[0].isObject() ? &f.regs.sp[0].toObject() : NULL;
JSObject *obj = js_CreateThisForFunctionWithProto(cx, callee, proto);
if (!obj)

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

@ -695,13 +695,12 @@ struct GetPropHelper {
// These fields are set in the constructor and describe a property lookup.
JSContext *cx;
JSObject *obj;
PropertyName *name;
RootedVarPropertyName name;
IC &ic;
VMFrame &f;
// These fields are set by |bind| and |lookup|. After a call to either
// function, these are set exactly as they are in JSOP_GETPROP or JSOP_NAME.
JSObject *aobj;
JSObject *holder;
JSProperty *prop;
@ -710,13 +709,13 @@ struct GetPropHelper {
const Shape *shape;
GetPropHelper(JSContext *cx, JSObject *obj, PropertyName *name, IC &ic, VMFrame &f)
: cx(cx), obj(obj), name(name), ic(ic), f(f), holder(NULL), prop(NULL), shape(NULL)
: cx(cx), obj(obj), name(cx, name), ic(ic), f(f), holder(NULL), prop(NULL), shape(NULL)
{ }
public:
LookupStatus bind() {
RecompilationMonitor monitor(cx);
JSObject *scopeChain = cx->stack.currentScriptedScopeChain();
RootedVarObject scopeChain(cx, cx->stack.currentScriptedScopeChain());
if (js_CodeSpec[*f.pc()].format & JOF_GNAME)
scopeChain = &scopeChain->global();
if (!FindProperty(cx, name, scopeChain, &obj, &holder, &prop))
@ -734,7 +733,9 @@ struct GetPropHelper {
}
LookupStatus lookup() {
JSObject *aobj = js_GetProtoIfDenseArray(obj);
JSObject *aobj = obj;
if (obj->isDenseArray())
aobj = obj->getProto();
if (!aobj->isNative())
return ic.disable(f, "non-native");
@ -2380,8 +2381,7 @@ GetElementIC::update(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *
/*
* Only treat this as a GETPROP for non-numeric string identifiers. The
* GETPROP IC assumes the id has already gone through filtering for string
* indexes in the emitter, i.e. js_GetProtoIfDenseArray is only valid to
* use when looking up non-integer identifiers.
* indexes in the emitter.
*/
uint32_t dummy;
if (v.isString() && JSID_IS_ATOM(id) && !JSID_TO_ATOM(id)->isIndex(&dummy))
@ -2421,7 +2421,7 @@ ic::GetElement(VMFrame &f, ic::GetElementIC *ic)
RecompilationMonitor monitor(cx);
JSObject *obj = ValueToObject(cx, f.regs.sp[-2]);
RootedVarObject obj(cx, ValueToObject(cx, f.regs.sp[-2]));
if (!obj)
THROW();

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

@ -216,11 +216,14 @@ stubs::ToId(VMFrame &f)
}
void JS_FASTCALL
stubs::ImplicitThis(VMFrame &f, PropertyName *name)
stubs::ImplicitThis(VMFrame &f, PropertyName *name_)
{
RootedVarObject scopeObj(f.cx, f.cx->stack.currentScriptedScopeChain());
RootedVarPropertyName name(f.cx, name_);
JSObject *obj, *obj2;
JSProperty *prop;
if (!FindPropertyHelper(f.cx, name, false, f.cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
if (!FindPropertyHelper(f.cx, name, false, scopeObj, &obj, &obj2, &prop))
THROW();
if (!ComputeImplicitThis(f.cx, obj, &f.regs.sp[0]))
@ -316,9 +319,9 @@ stubs::Ursh(VMFrame &f)
template<JSBool strict>
void JS_FASTCALL
stubs::DefFun(VMFrame &f, JSFunction *fun)
stubs::DefFun(VMFrame &f, JSFunction *fun_)
{
JSObject *obj2;
RootedVarFunction fun(f.cx, fun_);
JSContext *cx = f.cx;
StackFrame *fp = f.fp();
@ -331,6 +334,7 @@ stubs::DefFun(VMFrame &f, JSFunction *fun)
*/
JSObject *obj = fun;
RootedVarObject obj2(f.cx);
if (fun->isNullClosure()) {
/*
* Even a null closure needs a parent for principals finding.
@ -620,7 +624,7 @@ stubs::Add(VMFrame &f)
/* The string + string case is easily the hottest; try it first. */
bool lIsString = lval.isString();
bool rIsString = rval.isString();
JSString *lstr, *rstr;
RootedVarString lstr(cx), rstr(cx);
if (lIsString && rIsString) {
lstr = lval.toString();
rstr = rval.toString();
@ -924,7 +928,7 @@ stubs::NewInitObject(VMFrame &f, JSObject *baseobj)
JSObject *obj;
if (baseobj) {
obj = CopyInitializerObject(cx, baseobj);
obj = CopyInitializerObject(cx, RootedVarObject(cx, baseobj));
} else {
gc::AllocKind kind = GuessObjectGCKind(0);
obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
@ -999,9 +1003,11 @@ stubs::RegExp(VMFrame &f, JSObject *regex)
}
JSObject * JS_FASTCALL
stubs::Lambda(VMFrame &f, JSFunction *fun)
stubs::Lambda(VMFrame &f, JSFunction *fun_)
{
JSObject *parent;
RootedVarFunction fun(f.cx, fun_);
RootedVarObject parent(f.cx);
if (fun->isNullClosure()) {
parent = &f.fp()->scopeChain();
} else {
@ -1072,7 +1078,7 @@ InitPropOrMethod(VMFrame &f, PropertyName *name, JSOp op)
rval = regs.sp[-1];
/* Load the object being initialized into lval/obj. */
JSObject *obj = &regs.sp[-2].toObject();
RootedVarObject obj(cx, &regs.sp[-2].toObject());
JS_ASSERT(obj->isNative());
/* Get the immediate property name into id. */
@ -1113,7 +1119,7 @@ stubs::IterMore(VMFrame &f)
Value v;
JSObject *iterobj = &f.regs.sp[-1].toObject();
if (!js_IteratorMore(f.cx, iterobj, &v))
if (!js_IteratorMore(f.cx, RootedVarObject(f.cx, iterobj), &v))
THROWV(JS_FALSE);
return v.toBoolean();
@ -1416,11 +1422,14 @@ stubs::Pos(VMFrame &f)
}
void JS_FASTCALL
stubs::DelName(VMFrame &f, PropertyName *name)
stubs::DelName(VMFrame &f, PropertyName *name_)
{
RootedVarObject scopeObj(f.cx, f.cx->stack.currentScriptedScopeChain());
RootedVarPropertyName name(f.cx, name_);
JSObject *obj, *obj2;
JSProperty *prop;
if (!FindProperty(f.cx, name, f.cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
if (!FindProperty(f.cx, name, scopeObj, &obj, &obj2, &prop))
THROW();
/* Strict mode code should never contain JSOP_DELNAME opcodes. */
@ -1483,7 +1492,7 @@ stubs::DefVarOrConst(VMFrame &f, PropertyName *dn)
JSObject &obj = f.fp()->varObj();
if (!DefVarOrConstOperation(f.cx, obj, dn, attrs))
if (!DefVarOrConstOperation(f.cx, RootedVarObject(f.cx, &obj), dn, attrs))
THROW();
}

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

@ -2742,7 +2742,7 @@ ShapeOf(JSContext *cx, unsigned argc, jsval *vp)
* non-native referent may be simplified to data properties.
*/
static JSBool
CopyProperty(JSContext *cx, JSObject *obj, JSObject *referent, jsid id,
CopyProperty(JSContext *cx, JSObject *obj_, JSObject *referent, jsid id,
unsigned lookupFlags, JSObject **objp)
{
JSProperty *prop;
@ -2750,6 +2750,8 @@ CopyProperty(JSContext *cx, JSObject *obj, JSObject *referent, jsid id,
unsigned propFlags = 0;
JSObject *obj2;
RootedVarObject obj(cx, obj_);
*objp = NULL;
if (referent->isNative()) {
if (!LookupPropertyWithFlags(cx, referent, id, lookupFlags, &obj2, &prop))
@ -4301,9 +4303,11 @@ global_enumerate(JSContext *cx, JSObject *obj)
}
static JSBool
global_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
global_resolve(JSContext *cx, JSObject *obj_, jsid id, unsigned flags,
JSObject **objp)
{
RootedVarObject obj(cx, obj_);
#ifdef LAZY_STANDARD_CLASSES
JSBool resolved;

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

@ -86,11 +86,11 @@ js_PutArgsObject(StackFrame *fp)
}
ArgumentsObject *
ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee)
ArgumentsObject::create(JSContext *cx, uint32_t argc, HandleObject callee)
{
JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX);
JSObject *proto = callee.global().getOrCreateObjectPrototype(cx);
RootedVarObject proto(cx, callee->global().getOrCreateObjectPrototype(cx));
if (!proto)
return NULL;
@ -100,7 +100,7 @@ ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee)
if (!type)
return NULL;
bool strict = callee.toFunction()->inStrictMode();
bool strict = callee->toFunction()->inStrictMode();
Class *clasp = strict ? &StrictArgumentsObjectClass : &NormalArgumentsObjectClass;
RootedVarShape emptyArgumentsShape(cx);
@ -120,7 +120,7 @@ ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee)
if (!data)
return NULL;
data->callee.init(ObjectValue(callee));
data->callee.init(ObjectValue(*callee));
for (HeapValue *vp = data->slots; vp != data->slots + argc; vp++)
vp->init(UndefinedValue());
data->deletedBits = (size_t *)(data->slots + argc);
@ -149,7 +149,8 @@ ArgumentsObject::create(JSContext *cx, StackFrame *fp)
{
JS_ASSERT(fp->script()->needsArgsObj());
ArgumentsObject *argsobj = ArgumentsObject::create(cx, fp->numActualArgs(), fp->callee());
ArgumentsObject *argsobj = ArgumentsObject::create(cx, fp->numActualArgs(),
RootedVarObject(cx, &fp->callee()));
if (!argsobj)
return NULL;
@ -170,7 +171,7 @@ ArgumentsObject::create(JSContext *cx, StackFrame *fp)
ArgumentsObject *
ArgumentsObject::createUnexpected(JSContext *cx, StackFrame *fp)
{
ArgumentsObject *argsobj = create(cx, fp->numActualArgs(), fp->callee());
ArgumentsObject *argsobj = create(cx, fp->numActualArgs(), RootedVarObject(cx, &fp->callee()));
if (!argsobj)
return NULL;
@ -275,31 +276,31 @@ args_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
{
*objp = NULL;
NormalArgumentsObject &argsobj = obj->asNormalArguments();
RootedVar<NormalArgumentsObject*> argsobj(cx, &obj->asNormalArguments());
unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
if (JSID_IS_INT(id)) {
uint32_t arg = uint32_t(JSID_TO_INT(id));
if (arg >= argsobj.initialLength() || argsobj.isElementDeleted(arg))
if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
return true;
attrs |= JSPROP_ENUMERATE;
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
if (argsobj.hasOverriddenLength())
if (argsobj->hasOverriddenLength())
return true;
} else {
if (!JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom))
return true;
if (argsobj.callee().isMagic(JS_OVERWRITTEN_CALLEE))
if (argsobj->callee().isMagic(JS_OVERWRITTEN_CALLEE))
return true;
}
Value undef = UndefinedValue();
if (!js_DefineProperty(cx, &argsobj, id, &undef, ArgGetter, ArgSetter, attrs))
if (!js_DefineProperty(cx, argsobj, id, &undef, ArgGetter, ArgSetter, attrs))
return JS_FALSE;
*objp = &argsobj;
*objp = argsobj;
return true;
}
@ -404,12 +405,13 @@ StrictArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
if (!obj->isStrictArguments())
return true;
StrictArgumentsObject &argsobj = obj->asStrictArguments();
RootedVar<StrictArgumentsObject*> argsobj(cx, &obj->asStrictArguments());
RootId idRoot(cx, &id);
if (JSID_IS_INT(id)) {
unsigned arg = unsigned(JSID_TO_INT(id));
if (arg < argsobj.initialLength()) {
argsobj.setElement(arg, *vp);
if (arg < argsobj->initialLength()) {
argsobj->setElement(arg, *vp);
return true;
}
} else {
@ -423,8 +425,8 @@ StrictArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
* collect its value.
*/
AutoValueRooter tvr(cx);
return js_DeleteGeneric(cx, &argsobj, id, tvr.addr(), strict) &&
js_SetPropertyHelper(cx, &argsobj, id, 0, vp, strict);
return js_DeleteGeneric(cx, argsobj, id, tvr.addr(), strict) &&
js_SetPropertyHelper(cx, argsobj, id, 0, vp, strict);
}
static JSBool

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

@ -138,7 +138,7 @@ class ArgumentsObject : public JSObject
void initInitialLength(uint32_t length);
void initData(ArgumentsData *data);
static ArgumentsObject *create(JSContext *cx, uint32_t argc, JSObject &callee);
static ArgumentsObject *create(JSContext *cx, uint32_t argc, HandleObject callee);
public:
static const uint32_t RESERVED_SLOTS = 3;

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

@ -828,7 +828,7 @@ Debugger::newCompletionValue(JSContext *cx, JSTrapStatus status, Value value, Va
}
/* Common tail for JSTRAP_RETURN and JSTRAP_THROW. */
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass);
RootedVarObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass));
if (!obj ||
!wrapDebuggeeValue(cx, &value) ||
!DefineNativeProperty(cx, obj, key, value, JS_PropertyStub, JS_StrictPropertyStub,
@ -904,7 +904,7 @@ Debugger::parseResumptionValue(AutoCompartment &ac, bool ok, const Value &rv, Va
}
bool
CallMethodIfPresent(JSContext *cx, JSObject *obj, const char *name, int argc, Value *argv,
CallMethodIfPresent(JSContext *cx, HandleObject obj, const char *name, int argc, Value *argv,
Value *rval)
{
rval->setUndefined();
@ -1142,7 +1142,7 @@ Debugger::onTrap(JSContext *cx, Value *vp)
if (!dbg->getScriptFrame(cx, fp, &argv[0]))
return dbg->handleUncaughtException(ac, vp, false);
Value rv;
bool ok = CallMethodIfPresent(cx, bp->handler, "hit", 1, argv, &rv);
bool ok = CallMethodIfPresent(cx, RootedVarObject(cx, bp->handler), "hit", 1, argv, &rv);
JSTrapStatus st = dbg->parseResumptionValue(ac, ok, rv, vp, true);
if (st != JSTRAP_CONTINUE)
return st;
@ -3172,7 +3172,7 @@ DebuggerFrame_getArguments(JSContext *cx, unsigned argc, Value *vp)
return true;
}
JSObject *argsobj;
RootedVarObject argsobj(cx);
if (fp->hasArgs()) {
/* Create an arguments object. */
RootedVar<GlobalObject*> global(cx);
@ -3437,7 +3437,7 @@ DebuggerFrameEval(JSContext *cx, unsigned argc, Value *vp, EvalBindingsMode mode
if (!ac.enter())
return false;
Env *env = JS_GetFrameScopeChain(cx, Jsvalify(fp));
RootedVar<Env*> env(cx, JS_GetFrameScopeChain(cx, Jsvalify(fp)));
if (!env)
return false;
@ -3564,7 +3564,7 @@ DebuggerObject_checkThis(JSContext *cx, const CallArgs &args, const char *fnname
#define THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, fnname, args, obj) \
CallArgs args = CallArgsFromVp(argc, vp); \
JSObject *obj = DebuggerObject_checkThis(cx, args, fnname); \
RootedVarObject obj(cx, DebuggerObject_checkThis(cx, args, fnname)); \
if (!obj) \
return false; \
obj = (JSObject *) obj->getPrivate(); \
@ -3572,7 +3572,7 @@ DebuggerObject_checkThis(JSContext *cx, const CallArgs &args, const char *fnname
#define THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, fnname, args, dbg, obj) \
CallArgs args = CallArgsFromVp(argc, vp); \
JSObject *obj = DebuggerObject_checkThis(cx, args, fnname); \
RootedVarObject obj(cx, DebuggerObject_checkThis(cx, args, fnname)); \
if (!obj) \
return false; \
Debugger *dbg = Debugger::fromChildJSObject(obj); \
@ -3720,15 +3720,15 @@ DebuggerObject_getOwnPropertyDescriptor(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "getOwnPropertyDescriptor", args, dbg, obj);
jsid id;
if (!ValueToId(cx, argc >= 1 ? args[0] : UndefinedValue(), &id))
RootedVarId id(cx);
if (!ValueToId(cx, argc >= 1 ? args[0] : UndefinedValue(), id.address()))
return false;
/* Bug: This can cause the debuggee to run! */
AutoPropertyDescriptorRooter desc(cx);
{
AutoCompartment ac(cx, obj);
if (!ac.enter() || !cx->compartment->wrapId(cx, &id))
if (!ac.enter() || !cx->compartment->wrapId(cx, id.address()))
return false;
ErrorCopier ec(ac, dbg->toJSObject());
@ -3854,8 +3854,8 @@ DebuggerObject_defineProperty(JSContext *cx, unsigned argc, Value *vp)
THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "defineProperty", args, dbg, obj);
REQUIRE_ARGC("Debugger.Object.defineProperty", 2);
jsid id;
if (!ValueToId(cx, args[0], &id))
RootedVarId id(cx);
if (!ValueToId(cx, args[0], id.address()))
return JS_FALSE;
const Value &descval = args[1];
@ -3870,7 +3870,7 @@ DebuggerObject_defineProperty(JSContext *cx, unsigned argc, Value *vp)
{
AutoCompartment ac(cx, obj);
if (!ac.enter() || !WrapIdAndPropDesc(cx, obj, &id, desc))
if (!ac.enter() || !WrapIdAndPropDesc(cx, obj, id.address(), desc))
return false;
ErrorCopier ec(ac, dbg->toJSObject());
@ -3915,7 +3915,7 @@ DebuggerObject_defineProperties(JSContext *cx, unsigned argc, Value *vp)
ErrorCopier ec(ac, dbg->toJSObject());
for (size_t i = 0; i < n; i++) {
bool dummy;
if (!DefineProperty(cx, obj, ids[i], descs[i], true, &dummy))
if (!DefineProperty(cx, obj, RootedVarId(cx, ids[i]), descs[i], true, &dummy))
return false;
}
}

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

@ -142,6 +142,15 @@ js::ObjectImpl::nativeLookup(JSContext *cx, jsid id)
return Shape::search(cx, lastProperty(), id, &spp);
}
#ifdef DEBUG
const Shape *
js::ObjectImpl::nativeLookupNoAllocation(JSContext *cx, jsid id)
{
MOZ_ASSERT(isNative());
return Shape::searchNoAllocation(cx, lastProperty(), id);
}
#endif
void
js::ObjectImpl::markChildren(JSTracer *trc)
{

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

@ -747,6 +747,10 @@ class ObjectImpl : public gc::Cell
const Shape * nativeLookup(JSContext *cx, jsid id);
#ifdef DEBUG
const Shape * nativeLookupNoAllocation(JSContext *cx, jsid id);
#endif
inline Class *getClass() const;
inline JSClass *getJSClass() const;
inline bool hasClass(const Class *c) const;

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

@ -60,7 +60,7 @@ JS_STATIC_ASSERT(StickyFlag == JSREG_STICKY);
/* RegExpObjectBuilder */
RegExpObjectBuilder::RegExpObjectBuilder(JSContext *cx, RegExpObject *reobj)
: cx(cx), reobj_(reobj)
: cx(cx), reobj_(cx, reobj)
{}
bool
@ -93,7 +93,7 @@ RegExpObjectBuilder::getOrCreateClone(RegExpObject *proto)
}
RegExpObject *
RegExpObjectBuilder::build(JSAtom *source, RegExpShared &shared)
RegExpObjectBuilder::build(HandleAtom source, RegExpShared &shared)
{
if (!getOrCreate())
return NULL;
@ -106,16 +106,16 @@ RegExpObjectBuilder::build(JSAtom *source, RegExpShared &shared)
}
RegExpObject *
RegExpObjectBuilder::build(JSAtom *source, RegExpFlag flags)
RegExpObjectBuilder::build(HandleAtom source, RegExpFlag flags)
{
if (!getOrCreate())
return NULL;
return reobj_->init(cx, source, flags) ? reobj_ : NULL;
return reobj_->init(cx, source, flags) ? reobj_.raw() : NULL;
}
RegExpObject *
RegExpObjectBuilder::clone(RegExpObject *other, RegExpObject *proto)
RegExpObjectBuilder::clone(Handle<RegExpObject *> other, Handle<RegExpObject *> proto)
{
if (!getOrCreateClone(proto))
return NULL;
@ -130,14 +130,14 @@ RegExpObjectBuilder::clone(RegExpObject *other, RegExpObject *proto)
RegExpFlag staticsFlags = res->getFlags();
if ((origFlags & staticsFlags) != staticsFlags) {
RegExpFlag newFlags = RegExpFlag(origFlags | staticsFlags);
return build(other->getSource(), newFlags);
return build(RootedVar<JSLinearString*>(cx, other->getSource()), newFlags);
}
RegExpGuard g;
if (!other->getShared(cx, &g))
return NULL;
return build(other->getSource(), *g);
return build(RootedVarAtom(cx, other->getSource()), *g);
}
/* MatchPairs */
@ -373,7 +373,7 @@ RegExpObject *
RegExpObject::createNoStatics(JSContext *cx, const jschar *chars, size_t length, RegExpFlag flags,
TokenStream *tokenStream)
{
JSAtom *source = js_AtomizeChars(cx, chars, length);
RootedVarAtom source(cx, js_AtomizeChars(cx, chars, length));
if (!source)
return NULL;
@ -381,7 +381,7 @@ RegExpObject::createNoStatics(JSContext *cx, const jschar *chars, size_t length,
}
RegExpObject *
RegExpObject::createNoStatics(JSContext *cx, JSAtom *source, RegExpFlag flags,
RegExpObject::createNoStatics(JSContext *cx, HandleAtom source, RegExpFlag flags,
TokenStream *tokenStream)
{
if (!RegExpCode::checkSyntax(cx, tokenStream, source))
@ -415,6 +415,8 @@ RegExpObject::assignInitialShape(JSContext *cx)
JS_STATIC_ASSERT(MULTILINE_FLAG_SLOT == IGNORE_CASE_FLAG_SLOT + 1);
JS_STATIC_ASSERT(STICKY_FLAG_SLOT == MULTILINE_FLAG_SLOT + 1);
RootedVarObject self(cx, this);
/* The lastIndex property alone is writable but non-configurable. */
if (!addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.lastIndexAtom),
LAST_INDEX_SLOT, JSPROP_PERMANENT))
@ -423,25 +425,27 @@ RegExpObject::assignInitialShape(JSContext *cx)
}
/* Remaining instance properties are non-writable and non-configurable. */
if (!addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.sourceAtom),
SOURCE_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
!addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.globalAtom),
GLOBAL_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
!addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.ignoreCaseAtom),
IGNORE_CASE_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
!addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.multilineAtom),
MULTILINE_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY))
if (!self->addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.sourceAtom),
SOURCE_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
!self->addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.globalAtom),
GLOBAL_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
!self->addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.ignoreCaseAtom),
IGNORE_CASE_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
!self->addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.multilineAtom),
MULTILINE_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY))
{
return NULL;
}
return addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.stickyAtom),
STICKY_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY);
return self->addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.stickyAtom),
STICKY_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY);
}
inline bool
RegExpObject::init(JSContext *cx, JSAtom *source, RegExpFlag flags)
RegExpObject::init(JSContext *cx, HandleAtom source, RegExpFlag flags)
{
RootedVar<RegExpObject *> self(cx, this);
if (nativeEmpty()) {
if (isDelegate()) {
if (!assignInitialShape(cx))
@ -450,33 +454,37 @@ RegExpObject::init(JSContext *cx, JSAtom *source, RegExpFlag flags)
Shape *shape = assignInitialShape(cx);
if (!shape)
return false;
EmptyShape::insertInitialShape(cx, shape, getProto());
EmptyShape::insertInitialShape(cx, shape, self->getProto());
}
JS_ASSERT(!nativeEmpty());
JS_ASSERT(!self->nativeEmpty());
}
DebugOnly<JSAtomState *> atomState = &cx->runtime->atomState;
JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(atomState->lastIndexAtom))->slot() == LAST_INDEX_SLOT);
JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(atomState->sourceAtom))->slot() == SOURCE_SLOT);
JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(atomState->globalAtom))->slot() == GLOBAL_FLAG_SLOT);
JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(atomState->ignoreCaseAtom))->slot() ==
IGNORE_CASE_FLAG_SLOT);
JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(atomState->multilineAtom))->slot() ==
MULTILINE_FLAG_SLOT);
JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(atomState->stickyAtom))->slot() == STICKY_FLAG_SLOT);
JS_ASSERT(self->nativeLookupNoAllocation(cx, ATOM_TO_JSID(atomState->lastIndexAtom))->slot() ==
LAST_INDEX_SLOT);
JS_ASSERT(self->nativeLookupNoAllocation(cx, ATOM_TO_JSID(atomState->sourceAtom))->slot() ==
SOURCE_SLOT);
JS_ASSERT(self->nativeLookupNoAllocation(cx, ATOM_TO_JSID(atomState->globalAtom))->slot() ==
GLOBAL_FLAG_SLOT);
JS_ASSERT(self->nativeLookupNoAllocation(cx, ATOM_TO_JSID(atomState->ignoreCaseAtom))->slot() ==
IGNORE_CASE_FLAG_SLOT);
JS_ASSERT(self->nativeLookupNoAllocation(cx, ATOM_TO_JSID(atomState->multilineAtom))->slot() ==
MULTILINE_FLAG_SLOT);
JS_ASSERT(self->nativeLookupNoAllocation(cx, ATOM_TO_JSID(atomState->stickyAtom))->slot() ==
STICKY_FLAG_SLOT);
/*
* If this is a re-initialization with an existing RegExpShared, 'flags'
* may not match getShared()->flags, so forget the RegExpShared.
*/
JSObject::setPrivate(NULL);
self->JSObject::setPrivate(NULL);
zeroLastIndex();
setSource(source);
setGlobal(flags & GlobalFlag);
setIgnoreCase(flags & IgnoreCaseFlag);
setMultiline(flags & MultilineFlag);
setSticky(flags & StickyFlag);
self->zeroLastIndex();
self->setSource(source);
self->setGlobal(flags & GlobalFlag);
self->setIgnoreCase(flags & IgnoreCaseFlag);
self->setMultiline(flags & MultilineFlag);
self->setSticky(flags & StickyFlag);
return true;
}
@ -707,7 +715,8 @@ js::CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto)
JS_ASSERT(proto->isRegExp());
RegExpObjectBuilder builder(cx);
return builder.clone(&obj->asRegExp(), &proto->asRegExp());
return builder.clone(RootedVar<RegExpObject*>(cx, &obj->asRegExp()),
RootedVar<RegExpObject*>(cx, &proto->asRegExp()));
}
bool
@ -751,7 +760,7 @@ template<XDRMode mode>
bool
js::XDRScriptRegExpObject(XDRState<mode> *xdr, HeapPtrObject *objp)
{
JSAtom *source = 0;
RootedVarAtom source(xdr->cx());
uint32_t flagsword = 0;
if (mode == XDR_ENCODE) {
@ -760,7 +769,7 @@ js::XDRScriptRegExpObject(XDRState<mode> *xdr, HeapPtrObject *objp)
source = reobj.getSource();
flagsword = reobj.getFlags();
}
if (!XDRAtom(xdr, &source) || !xdr->codeUint32(&flagsword))
if (!XDRAtom(xdr, source.address()) || !xdr->codeUint32(&flagsword))
return false;
if (mode == XDR_DECODE) {
RegExpFlag flags = RegExpFlag(flagsword);

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

@ -44,6 +44,7 @@
#include "mozilla/Attributes.h"
#include <stddef.h>
#include "jscntxt.h"
#include "jsobj.h"
#include "js/TemplateLib.h"
@ -87,8 +88,8 @@ enum RegExpRunStatus
class RegExpObjectBuilder
{
JSContext *cx;
RegExpObject *reobj_;
JSContext *cx;
RootedVar<RegExpObject*> reobj_;
bool getOrCreate();
bool getOrCreateClone(RegExpObject *proto);
@ -98,11 +99,11 @@ class RegExpObjectBuilder
RegExpObject *reobj() { return reobj_; }
RegExpObject *build(JSAtom *source, RegExpFlag flags);
RegExpObject *build(JSAtom *source, RegExpShared &shared);
RegExpObject *build(HandleAtom source, RegExpFlag flags);
RegExpObject *build(HandleAtom source, RegExpShared &shared);
/* Perform a VM-internal clone. */
RegExpObject *clone(RegExpObject *other, RegExpObject *proto);
RegExpObject *clone(Handle<RegExpObject*> other, Handle<RegExpObject*> proto);
};
JSObject *
@ -366,7 +367,7 @@ class RegExpObject : public JSObject
TokenStream *ts);
static RegExpObject *
createNoStatics(JSContext *cx, JSAtom *atom, RegExpFlag flags, TokenStream *ts);
createNoStatics(JSContext *cx, HandleAtom atom, RegExpFlag flags, TokenStream *ts);
/*
* Run the regular expression over the input text.
@ -433,7 +434,7 @@ class RegExpObject : public JSObject
*/
Shape *assignInitialShape(JSContext *cx);
inline bool init(JSContext *cx, JSAtom *source, RegExpFlag flags);
inline bool init(JSContext *cx, HandleAtom source, RegExpFlag flags);
/*
* Precondition: the syntax for |source| has already been validated.

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

@ -66,11 +66,12 @@ ScopeObject::enclosingScope() const
}
inline bool
ScopeObject::setEnclosingScope(JSContext *cx, JSObject &obj)
ScopeObject::setEnclosingScope(JSContext *cx, HandleObject obj)
{
if (!obj.setDelegate(cx))
RootedVarObject self(cx, this);
if (!obj->setDelegate(cx))
return false;
setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(obj));
self->setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(*obj));
return true;
}

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

@ -149,7 +149,7 @@ js_PutCallObject(StackFrame *fp)
* must be null.
*/
CallObject *
CallObject::create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObject *callee)
CallObject::create(JSContext *cx, JSScript *script, HandleObject enclosing, HandleObject callee)
{
RootedVarShape shape(cx);
shape = script->bindings.callObjectShape(cx);
@ -159,7 +159,6 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObjec
gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots() + 1);
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
@ -168,7 +167,7 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObjec
if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
return NULL;
JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
RootedVarObject obj(cx, JSObject::create(cx, kind, shape, type, slots));
if (!obj)
return NULL;
@ -177,7 +176,7 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObjec
* whose call objects do not have a consistent global variable and need
* to be updated dynamically.
*/
JSObject &global = enclosing.global();
JSObject &global = enclosing->global();
if (&global != obj->getParent()) {
JS_ASSERT(obj->getParent() == NULL);
if (!obj->setParent(cx, &global))
@ -205,8 +204,10 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObjec
* If |bindings| is for a function that has extensible parents, that means
* its Call should have its own shape; see BaseShape::extensibleParents.
*/
if (obj->lastProperty()->extensibleParents() && !obj->generateOwnShape(cx))
return NULL;
if (obj->lastProperty()->extensibleParents()) {
if (!obj->generateOwnShape(cx))
return NULL;
}
return &obj->asCall();
}
@ -217,7 +218,7 @@ CallObject::createForFunction(JSContext *cx, StackFrame *fp)
JS_ASSERT(fp->isNonEvalFunctionFrame());
JS_ASSERT(!fp->hasCallObj());
JSObject *scopeChain = &fp->scopeChain();
RootedVarObject scopeChain(cx, &fp->scopeChain());
JS_ASSERT_IF(scopeChain->isWith() || scopeChain->isBlock() || scopeChain->isCall(),
scopeChain->getPrivate() != fp);
@ -237,7 +238,7 @@ CallObject::createForFunction(JSContext *cx, StackFrame *fp)
}
}
CallObject *callobj = create(cx, fp->script(), *scopeChain, &fp->callee());
CallObject *callobj = create(cx, fp->script(), scopeChain, RootedVarObject(cx, &fp->callee()));
if (!callobj)
return NULL;
@ -249,7 +250,9 @@ CallObject::createForFunction(JSContext *cx, StackFrame *fp)
CallObject *
CallObject::createForStrictEval(JSContext *cx, StackFrame *fp)
{
CallObject *callobj = create(cx, fp->script(), fp->scopeChain(), NULL);
CallObject *callobj = create(cx, fp->script(),
RootedVarObject(cx, &fp->scopeChain()),
RootedVarObject(cx));
if (!callobj)
return NULL;
@ -428,24 +431,24 @@ DeclEnvObject::create(JSContext *cx, StackFrame *fp)
return NULL;
obj->setPrivate(fp);
if (!obj->asScope().setEnclosingScope(cx, fp->scopeChain()))
if (!obj->asScope().setEnclosingScope(cx, RootedVarObject(cx, &fp->scopeChain())))
return NULL;
return &obj->asDeclEnv();
}
WithObject *
WithObject::create(JSContext *cx, StackFrame *fp, JSObject &proto, JSObject &enclosing,
WithObject::create(JSContext *cx, StackFrame *fp, HandleObject proto, HandleObject enclosing,
uint32_t depth)
{
RootedVarTypeObject type(cx);
type = proto.getNewType(cx);
type = proto->getNewType(cx);
if (!type)
return NULL;
RootedVarShape emptyWithShape(cx);
emptyWithShape = EmptyShape::getInitialShape(cx, &WithClass, &proto,
&enclosing.global(), FINALIZE_KIND);
emptyWithShape = EmptyShape::getInitialShape(cx, &WithClass, proto,
&enclosing->global(), FINALIZE_KIND);
if (!emptyWithShape)
return NULL;
@ -459,7 +462,7 @@ WithObject::create(JSContext *cx, StackFrame *fp, JSObject &proto, JSObject &enc
obj->setReservedSlot(DEPTH_SLOT, PrivateUint32Value(depth));
obj->setPrivate(js_FloatingFrameIfGenerator(cx, fp));
JSObject *thisp = proto.thisObject(cx);
JSObject *thisp = proto->thisObject(cx);
if (!thisp)
return NULL;

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

@ -121,7 +121,7 @@ class ScopeObject : public JSObject
* enclosing scope of a ScopeObject is necessarily non-null.
*/
inline JSObject &enclosingScope() const;
inline bool setEnclosingScope(JSContext *cx, JSObject &obj);
inline bool setEnclosingScope(JSContext *cx, HandleObject obj);
/*
* The stack frame for this scope object, if the frame is still active.
@ -139,7 +139,7 @@ class CallObject : public ScopeObject
static const uint32_t CALLEE_SLOT = 1;
static CallObject *
create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObject *callee);
create(JSContext *cx, JSScript *script, HandleObject enclosing, HandleObject callee);
public:
static const uint32_t RESERVED_SLOTS = 3;
@ -219,7 +219,7 @@ class WithObject : public NestedScopeObject
static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT4;
static WithObject *
create(JSContext *cx, StackFrame *fp, JSObject &proto, JSObject &enclosing, uint32_t depth);
create(JSContext *cx, StackFrame *fp, HandleObject proto, HandleObject enclosing, uint32_t depth);
/* Return object for the 'this' class hook. */
JSObject &withThis() const;

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

@ -117,7 +117,7 @@ JSRope::init(JSString *left, JSString *right, size_t length)
}
JS_ALWAYS_INLINE JSRope *
JSRope::new_(JSContext *cx, JSString *left, JSString *right, size_t length)
JSRope::new_(JSContext *cx, js::HandleString left, js::HandleString right, size_t length)
{
if (!validateLength(cx, length))
return NULL;
@ -138,6 +138,7 @@ JSRope::markChildren(JSTracer *trc)
JS_ALWAYS_INLINE void
JSDependentString::init(JSLinearString *base, const jschar *chars, size_t length)
{
JS_ASSERT(!js::IsPoisonedPtr(base));
d.lengthAndFlags = buildLengthAndFlags(length, DEPENDENT_BIT);
d.u1.chars = chars;
d.s.u2.base = base;
@ -155,6 +156,15 @@ JSDependentString::new_(JSContext *cx, JSLinearString *base, const jschar *chars
JS_ASSERT(chars >= base->chars() && chars < base->chars() + base->length());
JS_ASSERT(length <= base->length() - (chars - base->chars()));
JS::Root<JSLinearString*> baseRoot(cx, &base);
/*
* The characters may be an internal pointer to a GC thing, so prevent them
* from being overwritten. For now this prevents strings used as dependent
* bases of other strings from being moved by the GC.
*/
JS::SkipRoot charsRoot(cx, &chars);
JSDependentString *str = (JSDependentString *)js_NewGCString(cx);
if (!str)
return NULL;

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

@ -306,7 +306,7 @@ JSRope::flatten(JSContext *maybecx)
}
JSString * JS_FASTCALL
js_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
js_ConcatStrings(JSContext *cx, HandleString left, HandleString right)
{
JS_ASSERT_IF(!left->isAtom(), left->compartment() == cx->compartment);
JS_ASSERT_IF(!right->isAtom(), right->compartment() == cx->compartment);

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

@ -432,8 +432,8 @@ class JSRope : public JSString
void init(JSString *left, JSString *right, size_t length);
public:
static inline JSRope *new_(JSContext *cx, JSString *left,
JSString *right, size_t length);
static inline JSRope *new_(JSContext *cx, js::HandleString left,
js::HandleString right, size_t length);
inline JSString *leftChild() const {
JS_ASSERT(isRope());
@ -498,6 +498,7 @@ class JSFlatString : public JSLinearString
{
friend class JSRope;
void morphExtensibleIntoDependent(JSLinearString *base) {
JS_ASSERT(!js::IsPoisonedPtr(base));
d.lengthAndFlags = buildLengthAndFlags(length(), DEPENDENT_BIT);
d.s.u2.base = base;
}

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

@ -53,10 +53,12 @@ JSObject::asString()
namespace js {
inline bool
StringObject::init(JSContext *cx, JSString *str)
StringObject::init(JSContext *cx, HandleString str)
{
JS_ASSERT(gc::GetGCKindSlots(getAllocKind()) == 2);
RootedVar<StringObject *> self(cx, this);
if (nativeEmpty()) {
if (isDelegate()) {
if (!assignInitialShape(cx))
@ -65,39 +67,40 @@ StringObject::init(JSContext *cx, JSString *str)
Shape *shape = assignInitialShape(cx);
if (!shape)
return false;
EmptyShape::insertInitialShape(cx, shape, getProto());
EmptyShape::insertInitialShape(cx, shape, self->getProto());
}
}
JS_ASSERT(!nativeEmpty());
JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))->slot() == LENGTH_SLOT);
JS_ASSERT(nativeLookupNoAllocation(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))->slot()
== LENGTH_SLOT);
self->setStringThis(str);
setStringThis(str);
return true;
}
inline StringObject *
StringObject::create(JSContext *cx, JSString *str)
StringObject::create(JSContext *cx, HandleString str)
{
JSObject *obj = NewBuiltinClassInstance(cx, &StringClass);
if (!obj)
return NULL;
StringObject &strobj = obj->asString();
if (!strobj.init(cx, str))
RootedVar<StringObject*> strobj(cx, &obj->asString());
if (!strobj->init(cx, str))
return NULL;
return &strobj;
return strobj;
}
inline StringObject *
StringObject::createWithProto(JSContext *cx, JSString *str, JSObject &proto)
StringObject::createWithProto(JSContext *cx, HandleString str, JSObject &proto)
{
JSObject *obj = NewObjectWithClassProto(cx, &StringClass, &proto, NULL);
if (!obj)
return NULL;
StringObject &strobj = obj->asString();
if (!strobj.init(cx, str))
RootedVar<StringObject*> strobj(cx, &obj->asString());
if (!strobj->init(cx, str))
return NULL;
return &strobj;
return strobj;
}
} // namespace js

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

@ -60,13 +60,13 @@ class StringObject : public JSObject
* Creates a new String object boxing the given string. The object's
* [[Prototype]] is determined from context.
*/
static inline StringObject *create(JSContext *cx, JSString *str);
static inline StringObject *create(JSContext *cx, HandleString str);
/*
* Identical to create(), but uses |proto| as [[Prototype]]. This method
* must not be used to create |String.prototype|.
*/
static inline StringObject *createWithProto(JSContext *cx, JSString *str, JSObject &proto);
static inline StringObject *createWithProto(JSContext *cx, HandleString str, JSObject &proto);
JSString *unbox() const {
return getFixedSlot(PRIMITIVE_VALUE_SLOT).toString();
@ -81,7 +81,7 @@ class StringObject : public JSObject
}
private:
inline bool init(JSContext *cx, JSString *str);
inline bool init(JSContext *cx, HandleString str);
void setStringThis(JSString *str) {
JS_ASSERT(getReservedSlot(PRIMITIVE_VALUE_SLOT).isUndefined());