Bug 713311 - give the remaining scope objects typed interfaces (r=waldo)

--HG--
rename : js/src/vm/CallObject-inl.h => js/src/vm/ScopeObject-inl.h
rename : js/src/vm/CallObject.cpp => js/src/vm/ScopeObject.cpp
rename : js/src/vm/CallObject.h => js/src/vm/ScopeObject.h
extra : rebase_source : 0efa6c9ac4ceb10f48fe7ee7b199333da2b54cd9
This commit is contained in:
Luke Wagner 2012-01-02 15:02:05 -08:00
parent c9f5077db7
commit 6e9feca701
75 changed files with 2040 additions and 1904 deletions

View File

@ -157,7 +157,7 @@ CPPSRCS = \
jsxml.cpp \
prmjtime.cpp \
sharkctl.cpp \
CallObject.cpp \
ScopeObject.cpp \
Debugger.cpp \
GlobalObject.cpp \
Stack.cpp \

View File

@ -244,7 +244,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder,
return false;
}
RegExpObject *reobj = builder.build(sourceObj.asRegExp());
RegExpObject *reobj = builder.build(&sourceObj.asRegExp());
if (!reobj)
return false;
*rval = ObjectValue(*reobj);
@ -300,7 +300,7 @@ regexp_compile(JSContext *cx, uintN argc, Value *vp)
if (!obj)
return ok;
RegExpObjectBuilder builder(cx, obj->asRegExp());
RegExpObjectBuilder builder(cx, &obj->asRegExp());
return CompileRegExpObject(cx, builder, args.length(), args.array(), &args.rval());
}
@ -339,7 +339,7 @@ regexp_toString(JSContext *cx, uintN argc, Value *vp)
if (!obj)
return ok;
JSString *str = obj->asRegExp()->toString(cx);
JSString *str = obj->asRegExp().toString(cx);
if (!str)
return false;
@ -453,14 +453,14 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
JSObject *proto = global->createBlankPrototype(cx, &RegExpClass);
if (!proto)
return NULL;
proto->setPrivate(NULL);
RegExpObject *reproto = proto->asRegExp();
RegExpObject *reproto = &proto->asRegExp();
RegExpObjectBuilder builder(cx, reproto);
if (!builder.build(cx->runtime->emptyString, RegExpFlag(0)))
return NULL;
@ -514,7 +514,7 @@ ExecuteRegExp(JSContext *cx, Native native, uintN argc, Value *vp)
if (!obj)
return ok;
RegExpObject *reobj = obj->asRegExp();
RegExpObject *reobj = &obj->asRegExp();
RegExpMatcher matcher(cx);
if (reobj->startsWithAtomizedGreedyStar()) {

View File

@ -192,9 +192,9 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
MUST_FLOW_THROUGH("out");
// We can specialize a bit for the given scope chain if that scope chain is the global object.
JSObject *globalObj = scopeChain && scopeChain == scopeChain->getGlobal()
? scopeChain->getGlobal()
: NULL;
JSObject *globalObj = scopeChain && scopeChain == &scopeChain->global()
? &scopeChain->global()
: NULL;
JS_ASSERT_IF(globalObj, globalObj->isNative());
JS_ASSERT_IF(globalObj, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalObj->getClass()));

View File

@ -190,12 +190,12 @@ EmitCheck(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t delta)
return offset;
}
static JSObject *
static StaticBlockObject &
CurrentBlock(BytecodeEmitter *bce)
{
JS_ASSERT(bce->topStmt->type == STMT_BLOCK || bce->topStmt->type == STMT_SWITCH);
JS_ASSERT(bce->topStmt->blockObj->isStaticBlock());
return bce->topStmt->blockObj;
return *bce->topStmt->blockObj;
}
static void
@ -225,11 +225,11 @@ UpdateDepth(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t target)
intN nuses, ndefs;
if (op == JSOP_ENTERBLOCK) {
nuses = 0;
ndefs = OBJ_BLOCK_COUNT(cx, CurrentBlock(bce));
ndefs = CurrentBlock(bce).slotCount();
} else if (op == JSOP_ENTERLET0) {
nuses = ndefs = OBJ_BLOCK_COUNT(cx, CurrentBlock(bce));
nuses = ndefs = CurrentBlock(bce).slotCount();
} else if (op == JSOP_ENTERLET1) {
nuses = ndefs = OBJ_BLOCK_COUNT(cx, CurrentBlock(bce)) + 1;
nuses = ndefs = CurrentBlock(bce).slotCount() + 1;
} else {
nuses = StackUses(NULL, pc);
ndefs = StackDefs(NULL, pc);
@ -1356,15 +1356,15 @@ frontend::PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_
}
void
frontend::PushBlockScope(TreeContext *tc, StmtInfo *stmt, JSObject *blockObj, ptrdiff_t top)
frontend::PushBlockScope(TreeContext *tc, StmtInfo *stmt, StaticBlockObject &blockObj, ptrdiff_t top)
{
PushStatement(tc, stmt, STMT_BLOCK, top);
stmt->flags |= SIF_SCOPE;
blockObj->setStaticBlockScopeChain(tc->blockChain);
blockObj.setEnclosingBlock(tc->blockChain);
stmt->downScope = tc->topScopeStmt;
tc->topScopeStmt = stmt;
tc->blockChain = blockObj;
stmt->blockObj = blockObj;
tc->blockChain = &blockObj;
stmt->blockObj = &blockObj;
}
/*
@ -1560,7 +1560,7 @@ EmitNonLocalJumpFixup(JSContext *cx, BytecodeEmitter *bce, StmtInfo *toStmt)
if (stmt->flags & SIF_SCOPE) {
FLUSH_POPS();
uintN blockObjCount = OBJ_BLOCK_COUNT(cx, stmt->blockObj);
uintN blockObjCount = stmt->blockObj->slotCount();
if (stmt->flags & SIF_FOR_BLOCK) {
/*
* For a for-let-in statement, pushing/popping the block is
@ -1649,7 +1649,7 @@ frontend::PopStatementTC(TreeContext *tc)
if (STMT_LINKS_SCOPE(stmt)) {
tc->topScopeStmt = stmt->downScope;
if (stmt->flags & SIF_SCOPE)
tc->blockChain = stmt->blockObj->staticBlockScopeChain();
tc->blockChain = stmt->blockObj->enclosingBlock();
}
}
@ -1691,17 +1691,13 @@ frontend::LexicalLookup(TreeContext *tc, JSAtom *atom, jsint *slotp, StmtInfo *s
if (!(stmt->flags & SIF_SCOPE))
continue;
JSObject *obj = stmt->blockObj;
JS_ASSERT(obj->isStaticBlock());
const Shape *shape = obj->nativeLookup(tc->parser->context, ATOM_TO_JSID(atom));
StaticBlockObject &blockObj = *stmt->blockObj;
const Shape *shape = blockObj.nativeLookup(tc->parser->context, ATOM_TO_JSID(atom));
if (shape) {
JS_ASSERT(shape->hasShortID());
if (slotp) {
JS_ASSERT(obj->getSlot(JSSLOT_BLOCK_DEPTH).isInt32());
*slotp = obj->getSlot(JSSLOT_BLOCK_DEPTH).toInt32() + shape->shortid();
}
if (slotp)
*slotp = blockObj.stackDepth() + shape->shortid();
return stmt;
}
}
@ -1963,29 +1959,28 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
if (!EmitObjectOp(cx, pn->pn_objbox, op, bce))
return false;
JSObject *blockObj = pn->pn_objbox->object;
JS_ASSERT(blockObj->isStaticBlock());
JS_ASSERT(blockObj->getSlot(JSSLOT_BLOCK_DEPTH).isUndefined());
StaticBlockObject &blockObj = pn->pn_objbox->object->asStaticBlock();
int depth = bce->stackDepth -
(OBJ_BLOCK_COUNT(cx, blockObj) + ((op == JSOP_ENTERLET1) ? 1 : 0));
(blockObj.slotCount() + ((op == JSOP_ENTERLET1) ? 1 : 0));
JS_ASSERT(depth >= 0);
OBJ_SET_BLOCK_DEPTH(cx, blockObj, depth);
blockObj.setStackDepth(depth);
int depthPlusFixed = AdjustBlockSlot(cx, bce, depth);
if (depthPlusFixed < 0)
return false;
uintN base = JSSLOT_FREE(&BlockClass);
for (uintN slot = base, limit = base + OBJ_BLOCK_COUNT(cx, blockObj); slot < limit; slot++) {
const Value &v = blockObj->getSlot(slot);
for (unsigned i = 0; i < blockObj.slotCount(); i++) {
Definition *dn = blockObj.maybeDefinitionParseNode(i);
blockObj.poisonDefinitionParseNode(i);
/* Beware the empty destructuring dummy. */
if (v.isUndefined()) {
JS_ASSERT(slot + 1 <= limit);
if (!dn) {
JS_ASSERT(i + 1 <= blockObj.slotCount());
continue;
}
Definition *dn = (Definition *) v.toPrivate();
JS_ASSERT(dn->isDefn());
JS_ASSERT(uintN(dn->frameSlot() + depthPlusFixed) < JS_BIT(16));
dn->pn_cookie.set(dn->pn_cookie.level(), uint16_t(dn->frameSlot() + depthPlusFixed));
@ -1996,14 +1991,6 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
JS_ASSERT(pnu->pn_cookie.isFree());
}
#endif
/*
* If this variable is closed over, and |eval| is not present, then
* then set a bit in dslots so the Method JIT can deoptimize this
* slot.
*/
bool isClosed = bce->shouldNoteClosedName(dn);
blockObj->setSlot(slot, BooleanValue(isClosed));
}
/*
@ -2013,10 +2000,10 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
*/
if ((bce->flags & TCF_FUN_EXTENSIBLE_SCOPE) ||
bce->bindings.extensibleParents()) {
Shape *newShape = Shape::setExtensibleParents(cx, blockObj->lastProperty());
Shape *newShape = Shape::setExtensibleParents(cx, blockObj.lastProperty());
if (!newShape)
return false;
blockObj->setLastPropertyInfallible(newShape);
blockObj.setLastPropertyInfallible(newShape);
}
return true;
@ -3227,10 +3214,10 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* If there are hoisted let declarations, their stack slots go under the
* discriminant's value so push their slots now and enter the block later.
*/
uint32_t blockCount = 0;
uint32_t blockObjCount = 0;
if (pn2->isKind(PNK_LEXICALSCOPE)) {
blockCount = OBJ_BLOCK_COUNT(cx, pn2->pn_objbox->object);
for (uint32_t i = 0; i < blockCount; ++i) {
blockObjCount = pn2->pn_objbox->object->asStaticBlock().slotCount();
for (uint32_t i = 0; i < blockObjCount; ++i) {
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
return JS_FALSE;
}
@ -3243,7 +3230,7 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
#if JS_HAS_BLOCK_SCOPE
if (pn2->isKind(PNK_LEXICALSCOPE)) {
PushBlockScope(bce, &stmtInfo, pn2->pn_objbox->object, -1);
PushBlockScope(bce, &stmtInfo, pn2->pn_objbox->object->asStaticBlock(), -1);
stmtInfo.type = STMT_SWITCH;
if (!EmitEnterBlock(cx, bce, pn2, JSOP_ENTERLET1))
return JS_FALSE;
@ -3710,7 +3697,7 @@ out:
#if JS_HAS_BLOCK_SCOPE
if (ok && pn->pn_right->isKind(PNK_LEXICALSCOPE))
EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockCount);
EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockObjCount);
#endif
}
return ok;
@ -5124,7 +5111,7 @@ EmitTry(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* guardJump at the next catch (the guard mismatch case).
*/
JS_ASSERT(pn3->isKind(PNK_LEXICALSCOPE));
count = OBJ_BLOCK_COUNT(cx, pn3->pn_objbox->object);
count = pn3->pn_objbox->object->asStaticBlock().slotCount();
if (!EmitTree(cx, bce, pn3))
return false;
@ -5363,8 +5350,7 @@ EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
JS_ASSERT(varList->isArity(PN_LIST));
ParseNode *letBody = pnLet->pn_right;
JS_ASSERT(letBody->isLet() && letBody->isKind(PNK_LEXICALSCOPE));
JSObject *blockObj = letBody->pn_objbox->object;
JS_ASSERT(blockObj->isStaticBlock());
StaticBlockObject &blockObj = letBody->pn_objbox->object->asStaticBlock();
ptrdiff_t letHeadOffset = bce->offset();
intN letHeadDepth = bce->stackDepth;
@ -5375,7 +5361,7 @@ EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
/* Push storage for hoisted let decls (e.g. 'let (x) { let y }'). */
uint32_t alreadyPushed = uintN(bce->stackDepth - letHeadDepth);
uint32_t blockObjCount = OBJ_BLOCK_COUNT(cx, blockObj);
uint32_t blockObjCount = blockObj.slotCount();
for (uint32_t i = alreadyPushed; i < blockObjCount; ++i) {
/* Tell the decompiler not to print the decl in the let head. */
if (NewSrcNote(cx, bce, SRC_CONTINUE) < 0)
@ -5408,7 +5394,7 @@ EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
}
JS_ASSERT(leaveOp == JSOP_LEAVEBLOCK || leaveOp == JSOP_LEAVEBLOCKEXPR);
EMIT_UINT16_IMM_OP(leaveOp, OBJ_BLOCK_COUNT(cx, blockObj));
EMIT_UINT16_IMM_OP(leaveOp, blockObj.slotCount());
ptrdiff_t bodyEnd = bce->offset();
JS_ASSERT(bodyEnd > bodyBegin);
@ -5506,8 +5492,7 @@ EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
StmtInfo stmtInfo;
ObjectBox *objbox = pn->pn_objbox;
JSObject *blockObj = objbox->object;
JS_ASSERT(blockObj->isStaticBlock());
StaticBlockObject &blockObj = objbox->object->asStaticBlock();
PushBlockScope(bce, &stmtInfo, blockObj, bce->offset());
/*
@ -5546,7 +5531,7 @@ EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return false;
}
EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, OBJ_BLOCK_COUNT(cx, blockObj));
EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockObj.slotCount());
return PopStatementBCE(cx, bce);
}
@ -5618,8 +5603,8 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
bool letDecl = pn1 && pn1->isKind(PNK_LEXICALSCOPE);
JS_ASSERT_IF(letDecl, pn1->isLet());
JSObject *blockObj = letDecl ? pn1->pn_objbox->object : NULL;
uint32_t blockObjCount = blockObj ? OBJ_BLOCK_COUNT(cx, blockObj) : 0;
StaticBlockObject *blockObj = letDecl ? &pn1->pn_objbox->object->asStaticBlock() : NULL;
uint32_t blockObjCount = blockObj ? blockObj->slotCount() : 0;
if (letDecl) {
/*
@ -5676,7 +5661,7 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
/* Enter the block before the loop body, after evaluating the obj. */
StmtInfo letStmt;
if (letDecl) {
PushBlockScope(bce, &letStmt, blockObj, bce->offset());
PushBlockScope(bce, &letStmt, *blockObj, bce->offset());
letStmt.flags |= SIF_FOR_BLOCK;
if (!EmitEnterBlock(cx, bce, pn1, JSOP_ENTERLET1))
return false;

View File

@ -138,7 +138,7 @@ struct StmtInfo {
ptrdiff_t continues; /* offset of last continue in loop */
union {
JSAtom *label; /* name of LABEL */
JSObject *blockObj; /* block scope object */
StaticBlockObject *blockObj;/* block scope object */
};
StmtInfo *down; /* info for enclosing statement */
StmtInfo *downScope; /* next enclosing lexical scope */
@ -299,7 +299,7 @@ struct TreeContext { /* tree context for semantic checks */
at non-zero depth in current paren tree */
StmtInfo *topStmt; /* top of statement info stack */
StmtInfo *topScopeStmt; /* top lexical scope statement */
JSObject *blockChain; /* compile time block scope chain (NB: one
StaticBlockObject *blockChain; /* compile 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
@ -834,7 +834,7 @@ PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_t top);
* (if generating code), PopStatementBCE.
*/
void
PushBlockScope(TreeContext *tc, StmtInfo *stmt, JSObject *blockObj, ptrdiff_t top);
PushBlockScope(TreeContext *tc, StmtInfo *stmt, StaticBlockObject &blockObj, ptrdiff_t top);
/*
* Pop tc->topStmt. If the top StmtInfo struct is not stack-allocated, it

View File

@ -179,8 +179,6 @@ Parser::setPrincipals(JSPrincipals *prin, JSPrincipals *originPrin)
ObjectBox *
Parser::newObjectBox(JSObject *obj)
{
JS_ASSERT(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
@ -853,18 +851,18 @@ struct BindData {
union {
struct {
VarContext varContext;
JSObject *blockObj;
StaticBlockObject *blockObj;
uintN overflow;
} let;
};
bool fresh;
void initLet(VarContext varContext, JSObject *blockObj, uintN overflow) {
void initLet(VarContext varContext, StaticBlockObject &blockObj, uintN overflow) {
this->pn = NULL;
this->op = JSOP_NOP;
this->binder = BindLet;
this->let.varContext = varContext;
this->let.blockObj = blockObj;
this->let.blockObj = &blockObj;
this->let.overflow = overflow;
}
@ -1930,8 +1928,8 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc)
if (!CheckStrictBinding(cx, tc, atom->asPropertyName(), pn))
return false;
JSObject *blockObj = data->let.blockObj;
uintN blockCount = OBJ_BLOCK_COUNT(cx, blockObj);
StaticBlockObject &blockObj = *data->let.blockObj;
uintN blockCount = blockObj.slotCount();
if (blockCount == JS_BIT(16)) {
ReportCompileErrorNumber(cx, TS(tc->parser), pn,
JSREPORT_ERROR, data->let.overflow);
@ -1968,26 +1966,23 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc)
*/
bool redeclared;
jsid id = ATOM_TO_JSID(atom);
const Shape *shape = blockObj->defineBlockVariable(cx, id, blockCount, &redeclared);
const Shape *shape = blockObj.addVar(cx, id, blockCount, &redeclared);
if (!shape) {
if (redeclared)
ReportRedeclaration(cx, tc, pn, false, atom);
return false;
}
/*
* Store pn temporarily in the shape-mapped slots in the static block
* object. This value is clobbered in EmitEnterBlock.
*/
blockObj->setSlot(shape->slot(), PrivateValue(pn));
/* Store pn in the static block object. */
blockObj.setDefinitionParseNode(blockCount, reinterpret_cast<Definition *>(pn));
return true;
}
template <class Op>
static inline bool
ForEachLetDef(TreeContext *tc, JSObject *blockObj, Op op)
ForEachLetDef(TreeContext *tc, StaticBlockObject &blockObj, Op op)
{
for (Shape::Range r = blockObj->lastProperty()->all(); !r.empty(); r.popFront()) {
for (Shape::Range r = blockObj.lastProperty()->all(); !r.empty(); r.popFront()) {
const Shape &shape = r.front();
/* Beware the destructuring dummy slots. */
@ -2001,7 +1996,7 @@ ForEachLetDef(TreeContext *tc, JSObject *blockObj, Op op)
}
struct RemoveDecl {
bool operator()(TreeContext *tc, JSObject *, const Shape &, JSAtom *atom) {
bool operator()(TreeContext *tc, StaticBlockObject &, const Shape &, JSAtom *atom) {
tc->decls.remove(atom);
return true;
}
@ -2011,9 +2006,9 @@ static void
PopStatement(TreeContext *tc)
{
if (tc->topStmt->flags & SIF_SCOPE) {
JSObject *obj = tc->topStmt->blockObj;
JS_ASSERT(!obj->inDictionaryMode());
ForEachLetDef(tc, obj, RemoveDecl());
StaticBlockObject &blockObj = *tc->topStmt->blockObj;
JS_ASSERT(!blockObj.inDictionaryMode());
ForEachLetDef(tc, blockObj, RemoveDecl());
}
PopStatementTC(tc);
}
@ -2587,8 +2582,8 @@ CheckDestructuring(JSContext *cx, BindData *data, ParseNode *left, TreeContext *
return false;
}
JSObject *blockObj = data && data->binder == BindLet ? data->let.blockObj : NULL;
uint32_t blockCountBefore = blockObj ? OBJ_BLOCK_COUNT(cx, blockObj) : 0;
StaticBlockObject *blockObj = data && data->binder == BindLet ? data->let.blockObj : NULL;
uint32_t blockCountBefore = blockObj ? blockObj->slotCount() : 0;
if (left->isKind(PNK_RB)) {
for (ParseNode *pn = left->pn_head; pn; pn = pn->pn_next) {
@ -2658,7 +2653,7 @@ CheckDestructuring(JSContext *cx, BindData *data, ParseNode *left, TreeContext *
* corresponding dummy property to the block object) for each initializer
* that doesn't introduce at least one binding.
*/
if (toplevel && blockObj && blockCountBefore == OBJ_BLOCK_COUNT(cx, blockObj)) {
if (toplevel && blockObj && blockCountBefore == blockObj->slotCount()) {
if (!DefineNativeProperty(cx, blockObj,
INT_TO_JSID(blockCountBefore),
UndefinedValue(), NULL, NULL,
@ -2666,7 +2661,7 @@ CheckDestructuring(JSContext *cx, BindData *data, ParseNode *left, TreeContext *
Shape::HAS_SHORTID, blockCountBefore)) {
return false;
}
JS_ASSERT(OBJ_BLOCK_COUNT(cx, blockObj) == blockCountBefore + 1);
JS_ASSERT(blockObj->slotCount() == blockCountBefore + 1);
}
return true;
@ -2811,13 +2806,13 @@ Parser::returnOrYield(bool useAssignExpr)
}
static ParseNode *
PushLexicalScope(JSContext *cx, TreeContext *tc, JSObject *obj, StmtInfo *stmt)
PushLexicalScope(JSContext *cx, TreeContext *tc, StaticBlockObject &obj, StmtInfo *stmt)
{
ParseNode *pn = LexicalScopeNode::create(PNK_LEXICALSCOPE, tc);
if (!pn)
return NULL;
ObjectBox *blockbox = tc->parser->newObjectBox(obj);
ObjectBox *blockbox = tc->parser->newObjectBox(&obj);
if (!blockbox)
return NULL;
@ -2835,11 +2830,11 @@ PushLexicalScope(JSContext *cx, TreeContext *tc, JSObject *obj, StmtInfo *stmt)
static ParseNode *
PushLexicalScope(JSContext *cx, TreeContext *tc, StmtInfo *stmt)
{
JSObject *obj = js_NewBlockObject(cx);
if (!obj)
StaticBlockObject *blockObj = StaticBlockObject::create(cx);
if (!blockObj)
return NULL;
return PushLexicalScope(cx, tc, obj, stmt);
return PushLexicalScope(cx, tc, *blockObj, stmt);
}
#if JS_HAS_BLOCK_SCOPE
@ -2850,16 +2845,16 @@ struct AddDecl
AddDecl(uint32_t blockid) : blockid(blockid) {}
bool operator()(TreeContext *tc, JSObject *blockObj, const Shape &shape, JSAtom *atom)
bool operator()(TreeContext *tc, StaticBlockObject &blockObj, const Shape &shape, JSAtom *atom)
{
ParseNode *def = (ParseNode *) blockObj->getSlot(shape.slot()).toPrivate();
ParseNode *def = (ParseNode *) blockObj.getSlot(shape.slot()).toPrivate();
def->pn_blockid = blockid;
return Define(def, atom, tc, true);
}
};
static ParseNode *
PushLetScope(JSContext *cx, TreeContext *tc, JSObject *blockObj, StmtInfo *stmt)
PushLetScope(JSContext *cx, TreeContext *tc, StaticBlockObject &blockObj, StmtInfo *stmt)
{
ParseNode *pn = PushLexicalScope(cx, tc, blockObj, stmt);
if (!pn)
@ -2889,7 +2884,7 @@ Parser::letBlock(LetContext letContext)
if (!pnlet)
return NULL;
JSObject *blockObj = js_NewBlockObject(context);
StaticBlockObject *blockObj = StaticBlockObject::create(context);
if (!blockObj)
return NULL;
@ -2902,7 +2897,7 @@ Parser::letBlock(LetContext letContext)
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_LET);
StmtInfo stmtInfo;
ParseNode *block = PushLetScope(context, tc, blockObj, &stmtInfo);
ParseNode *block = PushLetScope(context, tc, *blockObj, &stmtInfo);
if (!block)
return NULL;
@ -2969,7 +2964,7 @@ PushBlocklikeStatement(StmtInfo *stmt, StmtType type, TreeContext *tc)
}
static ParseNode *
NewBindingNode(JSAtom *atom, TreeContext *tc, JSObject *blockObj = NULL,
NewBindingNode(JSAtom *atom, TreeContext *tc, StaticBlockObject *blockObj = NULL,
VarContext varContext = HoistVars)
{
/*
@ -3169,7 +3164,7 @@ Parser::forStatement()
bool forDecl = false;
/* Non-null when forDecl is true for a 'for (let ...)' statement. */
JSObject *blockObj = NULL;
StaticBlockObject *blockObj = NULL;
/* Set to 'x' in 'for (x ;... ;...)' or 'for (x in ...)'. */
ParseNode *pn1;
@ -3210,7 +3205,7 @@ Parser::forStatement()
pn1 = letBlock(LetExpresion);
} else {
forDecl = true;
blockObj = js_NewBlockObject(context);
blockObj = StaticBlockObject::create(context);
if (!blockObj)
return NULL;
pn1 = variables(PNK_LET, blockObj, DontHoistVars);
@ -3371,7 +3366,7 @@ Parser::forStatement()
* created by PushLetScope around the for's initializer. This also
* serves to indicate the let-decl to the emitter.
*/
ParseNode *block = PushLetScope(context, tc, blockObj, &letStmt);
ParseNode *block = PushLetScope(context, tc, *blockObj, &letStmt);
if (!block)
return NULL;
letStmt.flags |= SIF_FOR_BLOCK;
@ -3428,7 +3423,7 @@ Parser::forStatement()
* Desugar 'for (let A; B; C) D' into 'let (A) { for (; B; C) D }'
* to induce the correct scoping for A.
*/
ParseNode *block = PushLetScope(context, tc, blockObj, &letStmt);
ParseNode *block = PushLetScope(context, tc, *blockObj, &letStmt);
if (!block)
return NULL;
letStmt.flags |= SIF_FOR_BLOCK;
@ -3588,7 +3583,7 @@ Parser::tryStatement()
* scoped, not a property of a new Object instance. This is
* an intentional change that anticipates ECMA Ed. 4.
*/
data.initLet(HoistVars, tc->blockChain, JSMSG_TOO_MANY_CATCH_VARS);
data.initLet(HoistVars, *tc->blockChain, JSMSG_TOO_MANY_CATCH_VARS);
JS_ASSERT(data.let.blockObj && data.let.blockObj == pnblock->pn_objbox->object);
tt = tokenStream.getToken();
@ -3792,11 +3787,11 @@ Parser::letStatement()
JS_ASSERT(!stmt->downScope);
/* Convert the block statement into a scope statement. */
JSObject *obj = js_NewBlockObject(tc->parser->context);
if (!obj)
StaticBlockObject *blockObj = StaticBlockObject::create(tc->parser->context);
if (!blockObj)
return NULL;
ObjectBox *blockbox = tc->parser->newObjectBox(obj);
ObjectBox *blockbox = tc->parser->newObjectBox(blockObj);
if (!blockbox)
return NULL;
@ -3810,9 +3805,9 @@ Parser::letStatement()
stmt->downScope = tc->topScopeStmt;
tc->topScopeStmt = stmt;
obj->setStaticBlockScopeChain(tc->blockChain);
tc->blockChain = obj;
stmt->blockObj = obj;
blockObj->setEnclosingBlock(tc->blockChain);
tc->blockChain = blockObj;
stmt->blockObj = blockObj;
#ifdef DEBUG
ParseNode *tmp = tc->blockNode;
@ -4283,7 +4278,7 @@ Parser::statement()
* context, and the let-initializer of a for-statement.
*/
ParseNode *
Parser::variables(ParseNodeKind kind, JSObject *blockObj, VarContext varContext)
Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext varContext)
{
/*
* The four options here are:
@ -4308,7 +4303,7 @@ Parser::variables(ParseNodeKind kind, JSObject *blockObj, VarContext varContext)
*/
BindData data;
if (blockObj)
data.initLet(varContext, blockObj, JSMSG_TOO_MANY_LOCALS);
data.initLet(varContext, *blockObj, JSMSG_TOO_MANY_LOCALS);
else
data.initVarOrConst(pn->getOp());
@ -5369,7 +5364,7 @@ Parser::comprehensionTail(ParseNode *kid, uintN blockid, bool isGenexp,
transplanter.transplant(kid);
JS_ASSERT(tc->blockChain && tc->blockChain == pn->pn_objbox->object);
data.initLet(HoistVars, tc->blockChain, JSMSG_ARRAY_INIT_TOO_BIG);
data.initLet(HoistVars, *tc->blockChain, JSMSG_ARRAY_INIT_TOO_BIG);
do {
/*

View File

@ -60,6 +60,8 @@ typedef struct BindData BindData;
namespace js {
class StaticBlockObject;
enum FunctionSyntaxKind { Expression, Statement };
enum LetContext { LetExpresion, LetStatement };
enum VarContext { HoistVars, DontHoistVars };
@ -198,7 +200,8 @@ struct Parser : private AutoGCRooter
ParseNode *letStatement();
#endif
ParseNode *expressionStatement();
ParseNode *variables(ParseNodeKind kind, JSObject *blockObj = NULL, VarContext varContext = HoistVars);
ParseNode *variables(ParseNodeKind kind, StaticBlockObject *blockObj = NULL,
VarContext varContext = HoistVars);
ParseNode *expr();
ParseNode *assignExpr();
ParseNode *condExpr1();

View File

@ -86,14 +86,14 @@ ExhaustiveTest(const char funcode[])
EVAL(funcode, &v);
EVAL(CALL_CODES[ArgCount], &v);
ArgumentsObject *argsobj = JSVAL_TO_OBJECT(v)->asArguments();
ArgumentsObject &argsobj = JSVAL_TO_OBJECT(v)->asArguments();
Value elems[MAX_ELEMS];
for (size_t i = 0; i <= ArgCount; i++) {
for (size_t j = 0; j <= ArgCount - i; j++) {
ClearElements(elems);
CHECK(argsobj->getElements(i, j, elems));
CHECK(argsobj.getElements(i, j, elems));
for (size_t k = 0; k < j; k++)
CHECK_SAME(elems[k], INT_TO_JSVAL(i + k));
for (size_t k = j; k < MAX_ELEMS - 1; k++)

View File

@ -1403,7 +1403,7 @@ JS_EnterCrossCompartmentCallStackFrame(JSContext *cx, JSStackFrame *target)
AssertNoGC(cx);
CHECK_REQUEST(cx);
return JS_EnterCrossCompartmentCall(cx, Valueify(target)->scopeChain().getGlobal());
return JS_EnterCrossCompartmentCall(cx, &Valueify(target)->scopeChain().global());
}
JS_PUBLIC_API(void)
@ -1743,7 +1743,7 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
assertSameCompartment(cx, obj);
return obj->asGlobal()->initStandardClasses(cx);
return obj->global().initStandardClasses(cx);
}
#define CLASP(name) (&name##Class)
@ -2168,7 +2168,7 @@ JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
{
AssertNoGC(cx);
assertSameCompartment(cx, obj);
return obj->getGlobal();
return &obj->global();
}
JS_PUBLIC_API(JSObject *)
@ -3223,7 +3223,7 @@ JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
JS_PUBLIC_API(JSObject *)
JS_GetParent(JSContext *cx, JSObject *obj)
{
JS_ASSERT(!obj->isInternalScope());
JS_ASSERT(!obj->isScope());
assertSameCompartment(cx, obj);
return obj->getParent();
}
@ -3233,7 +3233,7 @@ JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
{
AssertNoGC(cx);
CHECK_REQUEST(cx);
JS_ASSERT(!obj->isInternalScope());
JS_ASSERT(!obj->isScope());
JS_ASSERT(parent || !obj->getParent());
assertSameCompartment(cx, obj, parent);
return obj->setParent(cx, parent);
@ -3727,14 +3727,14 @@ DefineProperty(JSContext *cx, JSObject *obj, const char *name, const Value &valu
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
attrs &= ~JSPROP_NATIVE_ACCESSORS;
if (getter) {
JSObject *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, obj->getGlobal(), NULL);
JSObject *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, &obj->global(), NULL);
if (!getobj)
return false;
getter = JS_DATA_TO_FUNC_PTR(PropertyOp, getobj);
attrs |= JSPROP_GETTER;
}
if (setter) {
JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, obj->getGlobal(), NULL);
JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, &obj->global(), NULL);
if (!setobj)
return false;
setter = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setobj);
@ -4214,7 +4214,7 @@ JS_ClearScope(JSContext *cx, JSObject *obj)
/* Clear cached class objects on the global object. */
if (obj->isGlobal())
obj->asGlobal()->clear(cx);
obj->asGlobal().clear(cx);
js_InitRandom(cx);
}
@ -4603,7 +4603,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
return NULL;
}
obj = obj->scopeChain();
obj = obj->enclosingScope();
}
Value v;
@ -6289,7 +6289,7 @@ JS_NewRegExpObject(JSContext *cx, JSObject *obj, char *bytes, size_t length, uin
if (!chars)
return NULL;
RegExpStatics *res = obj->asGlobal()->getRegExpStatics();
RegExpStatics *res = obj->asGlobal().getRegExpStatics();
RegExpObject *reobj = RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
cx->free_(chars);
return reobj;
@ -6300,7 +6300,7 @@ JS_NewUCRegExpObject(JSContext *cx, JSObject *obj, jschar *chars, size_t length,
{
AssertNoGC(cx);
CHECK_REQUEST(cx);
RegExpStatics *res = obj->asGlobal()->getRegExpStatics();
RegExpStatics *res = obj->asGlobal().getRegExpStatics();
return RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
}
@ -6311,7 +6311,7 @@ JS_SetRegExpInput(JSContext *cx, JSObject *obj, JSString *input, JSBool multilin
CHECK_REQUEST(cx);
assertSameCompartment(cx, input);
obj->asGlobal()->getRegExpStatics()->reset(cx, input, !!multiline);
obj->asGlobal().getRegExpStatics()->reset(cx, input, !!multiline);
}
JS_PUBLIC_API(void)
@ -6321,7 +6321,7 @@ JS_ClearRegExpStatics(JSContext *cx, JSObject *obj)
CHECK_REQUEST(cx);
JS_ASSERT(obj);
obj->asGlobal()->getRegExpStatics()->clear();
obj->asGlobal().getRegExpStatics()->clear();
}
JS_PUBLIC_API(JSBool)
@ -6331,8 +6331,8 @@ JS_ExecuteRegExp(JSContext *cx, JSObject *obj, JSObject *reobj, jschar *chars, s
AssertNoGC(cx);
CHECK_REQUEST(cx);
RegExpStatics *res = obj->asGlobal()->getRegExpStatics();
return ExecuteRegExp(cx, res, reobj->asRegExp(), NULL, chars, length,
RegExpStatics *res = obj->asGlobal().getRegExpStatics();
return ExecuteRegExp(cx, res, &reobj->asRegExp(), NULL, chars, length,
indexp, test ? RegExpTest : RegExpExec, rval);
}
@ -6364,7 +6364,7 @@ JS_ExecuteRegExpNoStatics(JSContext *cx, JSObject *obj, jschar *chars, size_t le
AssertNoGC(cx);
CHECK_REQUEST(cx);
return ExecuteRegExp(cx, NULL, obj->asRegExp(), NULL, chars, length, indexp,
return ExecuteRegExp(cx, NULL, &obj->asRegExp(), NULL, chars, length, indexp,
test ? RegExpTest : RegExpExec, rval);
}
@ -6382,7 +6382,7 @@ JS_GetRegExpFlags(JSContext *cx, JSObject *obj)
AssertNoGC(cx);
CHECK_REQUEST(cx);
return obj->asRegExp()->getFlags();
return obj->asRegExp().getFlags();
}
JS_PUBLIC_API(JSString *)
@ -6391,7 +6391,7 @@ JS_GetRegExpSource(JSContext *cx, JSObject *obj)
AssertNoGC(cx);
CHECK_REQUEST(cx);
return obj->asRegExp()->getSource();
return obj->asRegExp().getSource();
}
/************************************************************************/

View File

@ -156,9 +156,9 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
}
if (obj->isArguments()) {
ArgumentsObject *argsobj = obj->asArguments();
if (!argsobj->hasOverriddenLength()) {
*lengthp = argsobj->initialLength();
ArgumentsObject &argsobj = obj->asArguments();
if (!argsobj.hasOverriddenLength()) {
*lengthp = argsobj.initialLength();
return true;
}
}
@ -415,7 +415,7 @@ GetElement(JSContext *cx, JSObject *obj, IndexType index, JSBool *hole, Value *v
return JS_TRUE;
}
if (obj->isArguments()) {
if (obj->asArguments()->getElement(uint32_t(index), vp)) {
if (obj->asArguments().getElement(uint32_t(index), vp)) {
*hole = JS_FALSE;
return true;
}
@ -452,9 +452,9 @@ GetElements(JSContext *cx, JSObject *aobj, jsuint length, Value *vp)
}
if (aobj->isArguments()) {
ArgumentsObject *argsobj = aobj->asArguments();
if (!argsobj->hasOverriddenLength()) {
if (argsobj->getElements(0, length, vp))
ArgumentsObject &argsobj = aobj->asArguments();
if (!argsobj.hasOverriddenLength()) {
if (argsobj.getElements(0, length, vp))
return true;
}
}
@ -3586,7 +3586,7 @@ js_InitArrayClass(JSContext *cx, JSObject *obj)
JS_ASSERT(obj->isNative());
RootedVar<GlobalObject*> global(cx);
global = obj->asGlobal();
global = &obj->asGlobal();
RootedVarObject arrayProto(cx);
arrayProto = global->createBlankPrototype(cx, &SlowArrayClass);

View File

@ -153,7 +153,7 @@ js_InitBooleanClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
JSObject *booleanProto = global->createBlankPrototype(cx, &BooleanClass);
if (!booleanProto)

View File

@ -523,9 +523,9 @@ JSStructuredCloneWriter::startWrite(const js::Value &v)
} else if (v.isObject()) {
JSObject *obj = &v.toObject();
if (obj->isRegExp()) {
RegExpObject *reobj = obj->asRegExp();
return out.writePair(SCTAG_REGEXP_OBJECT, reobj->getFlags()) &&
writeString(SCTAG_STRING, reobj->getSource());
RegExpObject &reobj = obj->asRegExp();
return out.writePair(SCTAG_REGEXP_OBJECT, reobj.getFlags()) &&
writeString(SCTAG_STRING, reobj.getSource());
} else if (obj->isDate()) {
jsdouble d = js_DateGetMsecSinceEpoch(context(), obj);
return out.writePair(SCTAG_DATE_OBJECT, 0) && out.writeDouble(d);

View File

@ -76,12 +76,12 @@ static inline GlobalObject *
GetGlobalForScopeChain(JSContext *cx)
{
if (cx->hasfp())
return cx->fp()->scopeChain().getGlobal();
return &cx->fp()->scopeChain().global();
JSObject *scope = JS_ObjectToInnerObject(cx, cx->globalObject);
if (!scope)
return NULL;
return scope->asGlobal();
return &scope->asGlobal();
}
inline GSNCache *

View File

@ -200,7 +200,7 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
*/
JSObject *global;
if (cx->hasfp()) {
global = cx->fp()->scopeChain().getGlobal();
global = &cx->fp()->scopeChain().global();
} else {
global = JS_ObjectToInnerObject(cx, cx->globalObject);
if (!global)

View File

@ -2647,7 +2647,7 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
/* Set the static LocalTZA. */
LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
JSObject *dateProto = global->createBlankPrototype(cx, &DateClass);
if (!dateProto)

View File

@ -647,7 +647,7 @@ JS_GetScriptFunction(JSContext *cx, JSScript *script)
JS_PUBLIC_API(JSObject *)
JS_GetParentOrScopeChain(JSContext *cx, JSObject *obj)
{
return obj->scopeChain();
return obj->enclosingScope();
}
JS_PUBLIC_API(JSBool)

View File

@ -1030,7 +1030,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
JS_ASSERT(obj->isGlobal());
JS_ASSERT(obj->isNative());
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
JSObject *objectProto;
if (!js_GetClassPrototype(cx, global, JSProto_Object, &objectProto))
@ -1333,7 +1333,7 @@ js_CopyErrorObject(JSContext *cx, JSObject *errobj, JSObject *scope)
// Create the Error object.
JSObject *proto;
if (!js_GetClassPrototype(cx, scope->getGlobal(), GetExceptionProtoKey(copy->exnType), &proto))
if (!js_GetClassPrototype(cx, &scope->global(), GetExceptionProtoKey(copy->exnType), &proto))
return NULL;
JSObject *copyobj = NewObjectWithGivenProto(cx, &ErrorClass, proto, NULL);
SetExnPrivate(cx, copyobj, copy);

View File

@ -92,7 +92,7 @@ JS_GetObjectFunction(JSObject *obj)
JS_FRIEND_API(JSObject *)
JS_GetGlobalForFrame(JSStackFrame *fp)
{
return Valueify(fp)->scopeChain().getGlobal();
return &Valueify(fp)->scopeChain().global();
}
JS_FRIEND_API(JSBool)
@ -197,25 +197,25 @@ js::IsSystemCompartment(const JSCompartment *c)
}
JS_FRIEND_API(bool)
js::IsScopeObject(const JSObject *obj)
js::IsScopeObject(JSObject *obj)
{
return obj->isInternalScope();
return obj->isScope();
}
JS_FRIEND_API(JSObject *)
js::GetObjectParentMaybeScope(const JSObject *obj)
js::GetObjectParentMaybeScope(JSObject *obj)
{
return obj->scopeChain();
return obj->enclosingScope();
}
JS_FRIEND_API(JSObject *)
js::GetGlobalForObjectCrossCompartment(JSObject *obj)
{
return obj->getGlobal();
return &obj->global();
}
JS_FRIEND_API(uint32_t)
js::GetObjectSlotSpan(const JSObject *obj)
js::GetObjectSlotSpan(JSObject *obj)
{
return obj->slotSpan();
}

View File

@ -285,7 +285,6 @@ extern JS_FRIEND_DATA(js::Class) NamespaceClass;
extern JS_FRIEND_DATA(js::Class) OuterWindowProxyClass;
extern JS_FRIEND_DATA(js::Class) ObjectProxyClass;
extern JS_FRIEND_DATA(js::Class) QNameClass;
extern JS_FRIEND_DATA(js::Class) ScriptClass;
extern JS_FRIEND_DATA(js::Class) XMLClass;
extern JS_FRIEND_DATA(js::Class) ObjectClass;
@ -302,17 +301,17 @@ GetObjectJSClass(const JSObject *obj)
}
JS_FRIEND_API(bool)
IsScopeObject(const JSObject *obj);
IsScopeObject(JSObject *obj);
inline JSObject *
GetObjectParent(const JSObject *obj)
GetObjectParent(JSObject *obj)
{
JS_ASSERT(!IsScopeObject(obj));
return reinterpret_cast<const shadow::Object*>(obj)->shape->base->parent;
return reinterpret_cast<shadow::Object*>(obj)->shape->base->parent;
}
JS_FRIEND_API(JSObject *)
GetObjectParentMaybeScope(const JSObject *obj);
GetObjectParentMaybeScope(JSObject *obj);
JS_FRIEND_API(JSObject *)
GetGlobalForObjectCrossCompartment(JSObject *obj);
@ -345,13 +344,13 @@ JS_FRIEND_API(void)
SetFunctionNativeReserved(JSObject *fun, size_t which, const Value &val);
inline JSObject *
GetObjectProto(const JSObject *obj)
GetObjectProto(JSObject *obj)
{
return reinterpret_cast<const shadow::Object*>(obj)->type->proto;
}
inline void *
GetObjectPrivate(const JSObject *obj)
GetObjectPrivate(JSObject *obj)
{
const shadow::Object *nobj = reinterpret_cast<const shadow::Object*>(obj);
void **addr = reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
@ -377,17 +376,17 @@ SetReservedSlot(JSObject *obj, size_t slot, const Value &value)
}
JS_FRIEND_API(uint32_t)
GetObjectSlotSpan(const JSObject *obj);
GetObjectSlotSpan(JSObject *obj);
inline const Value &
GetObjectSlot(const JSObject *obj, size_t slot)
GetObjectSlot(JSObject *obj, size_t slot)
{
JS_ASSERT(slot < GetObjectSlotSpan(obj));
return reinterpret_cast<const shadow::Object *>(obj)->slotRef(slot);
}
inline Shape *
GetObjectShape(const JSObject *obj)
GetObjectShape(JSObject *obj)
{
shadow::Shape *shape = reinterpret_cast<const shadow::Object*>(obj)->shape;
return reinterpret_cast<Shape *>(shape);

View File

@ -72,7 +72,7 @@
#include "frontend/BytecodeCompiler.h"
#include "frontend/BytecodeEmitter.h"
#include "frontend/TokenStream.h"
#include "vm/CallObject.h"
#include "vm/ScopeObject.h"
#include "vm/Debugger.h"
#if JS_HAS_GENERATORS
@ -92,7 +92,7 @@
#include "jsinferinlines.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "vm/CallObject-inl.h"
#include "vm/ScopeObject-inl.h"
#include "vm/ArgumentsObject-inl.h"
#include "vm/Stack-inl.h"
@ -104,7 +104,7 @@ using namespace js::types;
inline JSObject *
JSObject::getThrowTypeError() const
{
return getGlobal()->getThrowTypeError();
return global().getThrowTypeError();
}
JSBool
@ -127,7 +127,7 @@ ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee, StackFra
{
JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX);
JSObject *proto = callee.getGlobal()->getOrCreateObjectPrototype(cx);
JSObject *proto = callee.global().getOrCreateObjectPrototype(cx);
if (!proto)
return NULL;
@ -161,17 +161,17 @@ ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee, StackFra
if (!obj)
return NULL;
ArgumentsObject *argsobj = obj->asArguments();
ArgumentsObject &argsobj = obj->asArguments();
JS_ASSERT(UINT32_MAX > (uint64_t(argc) << PACKED_BITS_COUNT));
argsobj->initInitialLength(argc);
argsobj->initData(data);
argsobj->setStackFrame(strict ? NULL : fp);
argsobj.initInitialLength(argc);
argsobj.initData(data);
argsobj.setStackFrame(strict ? NULL : fp);
JS_ASSERT(argsobj->numFixedSlots() >= NormalArgumentsObject::RESERVED_SLOTS);
JS_ASSERT(argsobj->numFixedSlots() >= StrictArgumentsObject::RESERVED_SLOTS);
JS_ASSERT(argsobj.numFixedSlots() >= NormalArgumentsObject::RESERVED_SLOTS);
JS_ASSERT(argsobj.numFixedSlots() >= StrictArgumentsObject::RESERVED_SLOTS);
return argsobj;
return &argsobj;
}
struct STATIC_SKIP_INFERENCE PutArg
@ -251,15 +251,15 @@ js_PutArgsObject(StackFrame *fp)
static JSBool
args_delProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
ArgumentsObject *argsobj = obj->asArguments();
ArgumentsObject &argsobj = obj->asArguments();
if (JSID_IS_INT(id)) {
uintN arg = uintN(JSID_TO_INT(id));
if (arg < argsobj->initialLength())
argsobj->setElement(arg, MagicValue(JS_ARGS_HOLE));
if (arg < argsobj.initialLength())
argsobj.setElement(arg, MagicValue(JS_ARGS_HOLE));
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
argsobj->markLengthOverridden();
argsobj.markLengthOverridden();
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom)) {
argsobj->asNormalArguments()->clearCallee();
argsobj.asNormalArguments().clearCallee();
}
return true;
}
@ -270,26 +270,26 @@ ArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
if (!obj->isNormalArguments())
return true;
NormalArgumentsObject *argsobj = obj->asNormalArguments();
NormalArgumentsObject &argsobj = obj->asNormalArguments();
if (JSID_IS_INT(id)) {
/*
* arg can exceed the number of arguments if a script changed the
* prototype to point to another Arguments object with a bigger argc.
*/
uintN arg = uintN(JSID_TO_INT(id));
if (arg < argsobj->initialLength()) {
JS_ASSERT(!argsobj->element(arg).isMagic(JS_ARGS_HOLE));
if (StackFrame *fp = argsobj->maybeStackFrame())
if (arg < argsobj.initialLength()) {
JS_ASSERT(!argsobj.element(arg).isMagic(JS_ARGS_HOLE));
if (StackFrame *fp = argsobj.maybeStackFrame())
*vp = fp->canonicalActualArg(arg);
else
*vp = argsobj->element(arg);
*vp = argsobj.element(arg);
}
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
if (!argsobj->hasOverriddenLength())
vp->setInt32(argsobj->initialLength());
if (!argsobj.hasOverriddenLength())
vp->setInt32(argsobj.initialLength());
} else {
JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom));
const Value &v = argsobj->callee();
const Value &v = argsobj.callee();
if (!v.isMagic(JS_ARGS_HOLE))
*vp = v;
}
@ -302,12 +302,12 @@ ArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
if (!obj->isNormalArguments())
return true;
NormalArgumentsObject *argsobj = obj->asNormalArguments();
NormalArgumentsObject &argsobj = obj->asNormalArguments();
if (JSID_IS_INT(id)) {
uintN arg = uintN(JSID_TO_INT(id));
if (arg < argsobj->initialLength()) {
if (StackFrame *fp = argsobj->maybeStackFrame()) {
if (arg < argsobj.initialLength()) {
if (StackFrame *fp = argsobj.maybeStackFrame()) {
JSScript *script = fp->functionScript();
if (script->usesArguments) {
if (arg < fp->numFormalArgs())
@ -331,8 +331,8 @@ ArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
* that has a setter for this id.
*/
AutoValueRooter tvr(cx);
return js_DeleteProperty(cx, argsobj, id, tvr.addr(), false) &&
js_DefineProperty(cx, argsobj, id, vp, NULL, NULL, JSPROP_ENUMERATE);
return js_DeleteProperty(cx, &argsobj, id, tvr.addr(), false) &&
js_DefineProperty(cx, &argsobj, id, vp, NULL, NULL, JSPROP_ENUMERATE);
}
static JSBool
@ -341,44 +341,44 @@ args_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
{
*objp = NULL;
NormalArgumentsObject *argsobj = obj->asNormalArguments();
NormalArgumentsObject &argsobj = obj->asNormalArguments();
uintN attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
if (JSID_IS_INT(id)) {
uint32_t arg = uint32_t(JSID_TO_INT(id));
if (arg >= argsobj->initialLength() || argsobj->element(arg).isMagic(JS_ARGS_HOLE))
if (arg >= argsobj.initialLength() || argsobj.element(arg).isMagic(JS_ARGS_HOLE))
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_ARGS_HOLE))
if (argsobj.callee().isMagic(JS_ARGS_HOLE))
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;
}
static JSBool
args_enumerate(JSContext *cx, JSObject *obj)
{
NormalArgumentsObject *argsobj = obj->asNormalArguments();
NormalArgumentsObject &argsobj = obj->asNormalArguments();
/*
* Trigger reflection in args_resolve using a series of js_LookupProperty
* calls.
*/
int argc = int(argsobj->initialLength());
int argc = int(argsobj.initialLength());
for (int i = -2; i != argc; i++) {
jsid id = (i == -2)
? ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)
@ -388,7 +388,7 @@ args_enumerate(JSContext *cx, JSObject *obj)
JSObject *pobj;
JSProperty *prop;
if (!js_LookupProperty(cx, argsobj, id, &pobj, &prop))
if (!js_LookupProperty(cx, &argsobj, id, &pobj, &prop))
return false;
}
return true;
@ -400,7 +400,7 @@ StrictArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
if (!obj->isStrictArguments())
return true;
StrictArgumentsObject *argsobj = obj->asStrictArguments();
StrictArgumentsObject &argsobj = obj->asStrictArguments();
if (JSID_IS_INT(id)) {
/*
@ -408,15 +408,15 @@ StrictArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
* prototype to point to another Arguments object with a bigger argc.
*/
uintN arg = uintN(JSID_TO_INT(id));
if (arg < argsobj->initialLength()) {
const Value &v = argsobj->element(arg);
if (arg < argsobj.initialLength()) {
const Value &v = argsobj.element(arg);
if (!v.isMagic(JS_ARGS_HOLE))
*vp = v;
}
} else {
JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom));
if (!argsobj->hasOverriddenLength())
vp->setInt32(argsobj->initialLength());
if (!argsobj.hasOverriddenLength())
vp->setInt32(argsobj.initialLength());
}
return true;
}
@ -427,12 +427,12 @@ StrictArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
if (!obj->isStrictArguments())
return true;
StrictArgumentsObject *argsobj = obj->asStrictArguments();
StrictArgumentsObject &argsobj = obj->asStrictArguments();
if (JSID_IS_INT(id)) {
uintN arg = uintN(JSID_TO_INT(id));
if (arg < argsobj->initialLength()) {
argsobj->setElement(arg, *vp);
if (arg < argsobj.initialLength()) {
argsobj.setElement(arg, *vp);
return true;
}
} else {
@ -446,8 +446,8 @@ StrictArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
* collect its value.
*/
AutoValueRooter tvr(cx);
return js_DeleteProperty(cx, argsobj, id, tvr.addr(), strict) &&
js_SetPropertyHelper(cx, argsobj, id, 0, vp, strict);
return js_DeleteProperty(cx, &argsobj, id, tvr.addr(), strict) &&
js_SetPropertyHelper(cx, &argsobj, id, 0, vp, strict);
}
static JSBool
@ -455,7 +455,7 @@ strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject
{
*objp = NULL;
StrictArgumentsObject *argsobj = obj->asStrictArguments();
StrictArgumentsObject &argsobj = obj->asStrictArguments();
uintN attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
PropertyOp getter = StrictArgGetter;
@ -463,12 +463,12 @@ strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject
if (JSID_IS_INT(id)) {
uint32_t arg = uint32_t(JSID_TO_INT(id));
if (arg >= argsobj->initialLength() || argsobj->element(arg).isMagic(JS_ARGS_HOLE))
if (arg >= argsobj.initialLength() || argsobj.element(arg).isMagic(JS_ARGS_HOLE))
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) &&
@ -477,22 +477,22 @@ strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject
}
attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED;
getter = CastAsPropertyOp(argsobj->getThrowTypeError());
setter = CastAsStrictPropertyOp(argsobj->getThrowTypeError());
getter = CastAsPropertyOp(argsobj.getThrowTypeError());
setter = CastAsStrictPropertyOp(argsobj.getThrowTypeError());
}
Value undef = UndefinedValue();
if (!js_DefineProperty(cx, argsobj, id, &undef, getter, setter, attrs))
if (!js_DefineProperty(cx, &argsobj, id, &undef, getter, setter, attrs))
return false;
*objp = argsobj;
*objp = &argsobj;
return true;
}
static JSBool
strictargs_enumerate(JSContext *cx, JSObject *obj)
{
StrictArgumentsObject *argsobj = obj->asStrictArguments();
StrictArgumentsObject *argsobj = &obj->asStrictArguments();
/*
* Trigger reflection in strictargs_resolve using a series of
@ -524,16 +524,16 @@ strictargs_enumerate(JSContext *cx, JSObject *obj)
static void
args_finalize(JSContext *cx, JSObject *obj)
{
cx->free_(reinterpret_cast<void *>(obj->asArguments()->data()));
cx->free_(reinterpret_cast<void *>(obj->asArguments().data()));
}
static void
args_trace(JSTracer *trc, JSObject *obj)
{
ArgumentsObject *argsobj = obj->asArguments();
ArgumentsData *data = argsobj->data();
ArgumentsObject &argsobj = obj->asArguments();
ArgumentsData *data = argsobj.data();
MarkValue(trc, data->callee, js_callee_str);
MarkValueRange(trc, argsobj->initialLength(), data->slots, js_arguments_str);
MarkValueRange(trc, argsobj.initialLength(), data->slots, js_arguments_str);
/*
* If a generator's arguments or call object escapes, and the generator
@ -545,7 +545,7 @@ args_trace(JSTracer *trc, JSObject *obj)
* JSGenerator.
*/
#if JS_HAS_GENERATORS
StackFrame *fp = argsobj->maybeStackFrame();
StackFrame *fp = argsobj.maybeStackFrame();
if (fp && fp->isFloatingGenerator())
MarkObject(trc, js_FloatingFrameToGenerator(fp)->obj, "generator object");
#endif
@ -606,53 +606,6 @@ Class js::StrictArgumentsObjectClass = {
args_trace
};
/*
* A Declarative Environment object stores its active StackFrame pointer in
* its private slot, just as Call and Arguments objects do.
*/
Class js::DeclEnvClass = {
js_Object_str,
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(CallObject::DECL_ENV_RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub
};
static inline JSObject *
NewDeclEnvObject(JSContext *cx, StackFrame *fp)
{
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
JSObject *parent = fp->scopeChain().getGlobal();
RootedVarShape emptyDeclEnvShape(cx);
emptyDeclEnvShape =
EmptyShape::getInitialShape(cx, &DeclEnvClass, NULL,
parent, CallObject::DECL_ENV_FINALIZE_KIND);
if (!emptyDeclEnvShape)
return NULL;
JSObject *envobj = JSObject::create(cx, CallObject::DECL_ENV_FINALIZE_KIND,
emptyDeclEnvShape, type, NULL);
if (!envobj)
return NULL;
envobj->setPrivate(fp);
if (!envobj->setInternalScopeChain(cx, &fp->scopeChain()))
return NULL;
return envobj;
}
namespace js {
CallObject *
@ -670,7 +623,7 @@ CreateFunCallObject(JSContext *cx, StackFrame *fp)
* object holding function's name.
*/
if (JSAtom *lambdaName = CallObjectLambdaName(fp->fun())) {
scopeChain = NewDeclEnvObject(cx, fp);
scopeChain = DeclEnvObject::create(cx, fp);
if (!scopeChain)
return NULL;
@ -789,11 +742,9 @@ js_PutCallObject(StackFrame *fp)
/* Clear private pointers to fp, which is about to go away. */
if (js_IsNamedLambda(fun)) {
JSObject *env = callobj.internalScopeChain();
JS_ASSERT(env->isDeclEnv());
JS_ASSERT(env->getPrivate() == fp);
env->setPrivate(NULL);
JSObject &env = callobj.enclosingScope();
JS_ASSERT(env.asDeclEnv().maybeStackFrame() == fp);
env.setPrivate(NULL);
}
}
@ -1955,7 +1906,7 @@ Function(JSContext *cx, uintN argc, Value *vp)
/* Block this call if security callbacks forbid it. */
RootedVar<GlobalObject*> global(cx);
global = args.callee().getGlobal();
global = &args.callee().global();
if (!global->isRuntimeCodeGenEnabled(cx)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
return false;
@ -2250,7 +2201,7 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
if (!cscript)
return NULL;
cscript->globalObject = clone->getGlobal();
cscript->globalObject = &clone->global();
clone->setScript(cscript);
if (!cscript->typeSetFunction(cx, clone))
return NULL;

View File

@ -45,6 +45,8 @@
#include "vm/GlobalObject.h"
#include "vm/ScopeObject-inl.h"
inline bool
JSFunction::inStrictMode() const
{
@ -351,8 +353,8 @@ SkipScopeParent(JSObject *parent)
{
if (!parent)
return NULL;
while (parent->isInternalScope())
parent = parent->scopeChain();
while (parent->isScope())
parent = &parent->asScope().enclosingScope();
return parent;
}
@ -361,7 +363,7 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
gc::AllocKind kind = JSFunction::FinalizeKind)
{
JS_ASSERT(parent);
JSObject *proto = parent->getGlobal()->getOrCreateFunctionPrototype(cx);
JSObject *proto = parent->global().getOrCreateFunctionPrototype(cx);
if (!proto)
return NULL;
@ -395,7 +397,7 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun)
* Variant which makes an exact clone of fun, preserving parent and proto.
* Calling the above version CloneFunctionObject(cx, fun, fun->getParent())
* is not equivalent: API clients, including XPConnect, can reparent
* objects so that fun->getGlobal() != fun->getProto()->getGlobal().
* objects so that fun->global() != fun->getProto()->global().
* See ReparentWrapperIfFound.
*/
JS_ASSERT(fun->getParent() && fun->getProto());

View File

@ -96,7 +96,7 @@
#include "jsinterpinlines.h"
#include "jsobjinlines.h"
#include "vm/CallObject-inl.h"
#include "vm/ScopeObject-inl.h"
#include "vm/String-inl.h"
#ifdef MOZ_VALGRIND

View File

@ -1891,7 +1891,7 @@ TypeHasGlobal(Type type, JSObject *global)
return false;
if (type.isSingleObject())
return type.singleObject()->getGlobal() == global;
return &type.singleObject()->global() == global;
if (type.isTypeObject())
return type.typeObject()->getGlobal() == global;
@ -5199,8 +5199,8 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
return true;
}
JS_ASSERT_IF(fun && scope, fun->getGlobal() == scope->getGlobal());
script->types->global = fun ? fun->getGlobal() : scope->getGlobal();
JS_ASSERT_IF(fun && scope, fun->global() == scope->global());
script->types->global = fun ? &fun->global() : &scope->global();
/*
* Update the parent in the script's bindings. The bindings are created
@ -5231,7 +5231,7 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
* the script is nested inside.
*/
while (!scope->isCall())
scope = scope->internalScopeChain();
scope = &scope->asScope().enclosingScope();
CallObject &call = scope->asCall();
@ -5264,9 +5264,9 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
if (!parent->ensureHasTypes(cx))
return false;
if (!parent->types->hasScope()) {
if (!SetScope(cx, parent, scope->internalScopeChain()))
if (!SetScope(cx, parent, &call.enclosingScope()))
return false;
parent->nesting()->activeCall = scope;
parent->nesting()->activeCall = &call;
parent->nesting()->argArray = Valueify(call.argArray());
parent->nesting()->varArray = Valueify(call.varArray());
}
@ -5359,7 +5359,7 @@ CheckNestingParent(JSContext *cx, JSObject *scope, JSScript *script)
JS_ASSERT(parent);
while (!scope->isCall() || scope->asCall().getCalleeFunction()->script() != parent)
scope = scope->internalScopeChain();
scope = &scope->asScope().enclosingScope();
if (scope != parent->nesting()->activeCall) {
parent->reentrantOuterFunction = true;
@ -5374,7 +5374,7 @@ CheckNestingParent(JSContext *cx, JSObject *scope, JSScript *script)
* parent.
*/
if (parent->nesting()->parent) {
scope = scope->internalScopeChain();
scope = &scope->asScope().enclosingScope();
script = parent;
goto restart;
}

View File

@ -1250,9 +1250,9 @@ inline JSObject *
TypeObject::getGlobal()
{
if (singleton)
return singleton->getGlobal();
return &singleton->global();
if (interpretedFunction && interpretedFunction->script()->compileAndGo)
return interpretedFunction->getGlobal();
return &interpretedFunction->global();
return NULL;
}

View File

@ -139,7 +139,7 @@ using namespace js::types;
JSObject *
js::GetScopeChain(JSContext *cx, StackFrame *fp)
{
JSObject *sharedBlock = fp->maybeBlockChain();
StaticBlockObject *sharedBlock = fp->maybeBlockChain();
if (!sharedBlock) {
/*
@ -175,7 +175,7 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
*/
limitClone = &fp->scopeChain();
while (limitClone->isWith())
limitClone = limitClone->internalScopeChain();
limitClone = &limitClone->asWith().enclosingScope();
JS_ASSERT(limitClone);
/*
@ -207,10 +207,9 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
* Special-case cloning the innermost block; this doesn't have enough in
* common with subsequent steps to include in the loop.
*
* js_CloneBlockObject leaves the clone's parent slot uninitialized. We
* populate it below.
* create() leaves the clone's enclosingScope unset. We set it below.
*/
JSObject *innermostNewChild = js_CloneBlockObject(cx, sharedBlock, fp);
ClonedBlockObject *innermostNewChild = ClonedBlockObject::create(cx, *sharedBlock, fp);
if (!innermostNewChild)
return NULL;
@ -218,25 +217,25 @@ 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.
*/
JSObject *newChild = innermostNewChild;
ClonedBlockObject *newChild = innermostNewChild;
for (;;) {
JS_ASSERT(newChild->getProto() == sharedBlock);
sharedBlock = sharedBlock->staticBlockScopeChain();
sharedBlock = sharedBlock->enclosingBlock();
/* Sometimes limitBlock will be NULL, so check that first. */
if (sharedBlock == limitBlock || !sharedBlock)
break;
/* As in the call above, we don't know the real parent yet. */
JSObject *clone = js_CloneBlockObject(cx, sharedBlock, fp);
ClonedBlockObject *clone = ClonedBlockObject::create(cx, *sharedBlock, fp);
if (!clone)
return NULL;
if (!newChild->setInternalScopeChain(cx, clone))
if (!newChild->setEnclosingScope(cx, *clone))
return NULL;
newChild = clone;
}
if (!newChild->setInternalScopeChain(cx, &fp->scopeChain()))
if (!newChild->setEnclosingScope(cx, fp->scopeChain()))
return NULL;
@ -245,7 +244,7 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
* found it in blockChain.
*/
JS_ASSERT_IF(limitBlock &&
limitBlock->isBlock() &&
limitBlock->isClonedBlock() &&
limitClone->getPrivate() == js_FloatingFrameIfGenerator(cx, fp),
sharedBlock);
@ -327,7 +326,7 @@ js::BoxNonStrictThis(JSContext *cx, const CallReceiver &call)
#endif
if (thisv.isNullOrUndefined()) {
JSObject *thisp = call.callee().getGlobal()->thisObject(cx);
JSObject *thisp = call.callee().global().thisObject(cx);
if (!thisp)
return false;
call.thisv().setObject(*thisp);
@ -459,7 +458,7 @@ js::RunScript(JSContext *cx, JSScript *script, StackFrame *fp)
/* FIXME: Once bug 470510 is fixed, make this an assert. */
if (script->compileAndGo) {
if (fp->scopeChain().getGlobal()->isCleared()) {
if (fp->scopeChain().global().isCleared()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE);
return false;
}
@ -1088,8 +1087,8 @@ EnterWith(JSContext *cx, jsint stackIndex)
if (!obj)
return JS_FALSE;
JSObject *withobj = js_NewWithObject(cx, obj, parent,
sp + stackIndex - fp->base());
JSObject *withobj = WithObject::create(cx, fp, *obj, *parent,
sp + stackIndex - fp->base());
if (!withobj)
return JS_FALSE;
@ -1100,22 +1099,19 @@ EnterWith(JSContext *cx, jsint stackIndex)
static void
LeaveWith(JSContext *cx)
{
JSObject *withobj;
withobj = &cx->fp()->scopeChain();
JS_ASSERT(withobj->getClass() == &WithClass);
JS_ASSERT(withobj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()));
JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
withobj->setPrivate(NULL);
cx->fp()->setScopeChainNoCallObj(*withobj->internalScopeChain());
WithObject &withobj = cx->fp()->scopeChain().asWith();
JS_ASSERT(withobj.maybeStackFrame() == js_FloatingFrameIfGenerator(cx, cx->fp()));
JS_ASSERT(withobj.stackDepth() >= 0);
withobj.setStackFrame(NULL);
cx->fp()->setScopeChainNoCallObj(withobj.enclosingScope());
}
bool
js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, int stackDepth)
js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth)
{
return (obj.isWith() || obj.isBlock()) &&
obj.getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()) &&
OBJ_BLOCK_DEPTH(cx, &obj) >= stackDepth;
obj.asNestedScope().stackDepth() >= stackDepth;
}
/*
@ -1123,28 +1119,26 @@ js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, int stackDepth)
* fp->sp on return to stackDepth.
*/
bool
js::UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind)
js::UnwindScope(JSContext *cx, uint32_t stackDepth, JSBool normalUnwind)
{
JS_ASSERT(stackDepth >= 0);
JS_ASSERT(cx->fp()->base() + stackDepth <= cx->regs().sp);
StackFrame *fp = cx->fp();
JSObject *obj = fp->maybeBlockChain();
while (obj) {
JS_ASSERT(obj->isStaticBlock());
if (OBJ_BLOCK_DEPTH(cx, obj) < stackDepth)
StaticBlockObject *block = fp->maybeBlockChain();
while (block) {
if (block->stackDepth() < stackDepth)
break;
obj = obj->staticBlockScopeChain();
block = block->enclosingBlock();
}
fp->setBlockChain(obj);
fp->setBlockChain(block);
for (;;) {
JSObject &scopeChain = fp->scopeChain();
if (!IsActiveWithOrBlock(cx, scopeChain, stackDepth))
break;
if (scopeChain.isBlock()) {
if (scopeChain.isClonedBlock()) {
/* Don't fail until after we've updated all stacks. */
normalUnwind &= js_PutBlockObject(cx, normalUnwind);
normalUnwind &= scopeChain.asClonedBlock().put(cx, normalUnwind);
} else {
LeaveWith(cx);
}
@ -1922,17 +1916,17 @@ BEGIN_CASE(JSOP_POPN)
regs.sp -= GET_UINT16(regs.pc);
#ifdef DEBUG
JS_ASSERT(regs.fp()->base() <= regs.sp);
JSObject *obj = regs.fp()->maybeBlockChain();
JS_ASSERT_IF(obj,
OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
StaticBlockObject *block = regs.fp()->maybeBlockChain();
JS_ASSERT_IF(block,
block->stackDepth() + block->slotCount()
<= (size_t) (regs.sp - regs.fp()->base()));
for (obj = &regs.fp()->scopeChain(); obj; obj = obj->scopeChain()) {
for (JSObject *obj = &regs.fp()->scopeChain(); obj; obj = obj->enclosingScope()) {
if (!obj->isBlock() || !obj->isWith())
continue;
if (obj->getPrivate() != js_FloatingFrameIfGenerator(cx, regs.fp()))
break;
JS_ASSERT(regs.fp()->base() + OBJ_BLOCK_DEPTH(cx, obj)
+ (obj->isBlock() ? OBJ_BLOCK_COUNT(cx, obj) : 1)
JS_ASSERT(regs.fp()->base() + obj->asBlock().stackDepth()
+ (obj->isBlock() ? obj->asBlock().slotCount() : 1)
<= regs.sp);
}
#endif
@ -2345,7 +2339,7 @@ END_CASE(JSOP_ENUMCONSTELEM)
#endif
BEGIN_CASE(JSOP_BINDGNAME)
PUSH_OBJECT(*regs.fp()->scopeChain().getGlobal());
PUSH_OBJECT(regs.fp()->scopeChain().global());
END_CASE(JSOP_BINDGNAME)
BEGIN_CASE(JSOP_BINDNAME)
@ -2979,9 +2973,9 @@ BEGIN_CASE(JSOP_LENGTH)
}
if (obj->isArguments()) {
ArgumentsObject *argsobj = obj->asArguments();
if (!argsobj->hasOverriddenLength()) {
uint32_t length = argsobj->initialLength();
ArgumentsObject &argsobj = obj->asArguments();
if (!argsobj.hasOverriddenLength()) {
uint32_t length = argsobj.initialLength();
JS_ASSERT(length < INT32_MAX);
rval = Int32Value(int32_t(length));
break;
@ -3038,14 +3032,14 @@ BEGIN_CASE(JSOP_CALLPROP)
if (lval.isObject()) {
objv = lval;
} else {
GlobalObject *global = regs.fp()->scopeChain().getGlobal();
GlobalObject &global = regs.fp()->scopeChain().global();
JSObject *pobj;
if (lval.isString()) {
pobj = global->getOrCreateStringPrototype(cx);
pobj = global.getOrCreateStringPrototype(cx);
} else if (lval.isNumber()) {
pobj = global->getOrCreateNumberPrototype(cx);
pobj = global.getOrCreateNumberPrototype(cx);
} else if (lval.isBoolean()) {
pobj = global->getOrCreateBooleanPrototype(cx);
pobj = global.getOrCreateBooleanPrototype(cx);
} else {
JS_ASSERT(lval.isNull() || lval.isUndefined());
js_ReportIsNullOrUndefined(cx, -1, lval, NULL);
@ -3125,7 +3119,7 @@ BEGIN_CASE(JSOP_SETMETHOD)
JSObject *obj;
VALUE_TO_OBJECT(cx, &lref, obj);
JS_ASSERT_IF(op == JSOP_SETGNAME, obj == regs.fp()->scopeChain().getGlobal());
JS_ASSERT_IF(op == JSOP_SETGNAME, obj == &regs.fp()->scopeChain().global());
do {
PropertyCache *cache = &JS_PROPERTY_CACHE(cx);
@ -3258,7 +3252,7 @@ BEGIN_CASE(JSOP_GETELEM)
goto end_getelem;
}
} else if (obj->isArguments()) {
if (obj->asArguments()->getElement(index, &rval))
if (obj->asArguments().getElement(index, &rval))
goto end_getelem;
}
@ -3506,7 +3500,7 @@ BEGIN_CASE(JSOP_CALLNAME)
bool global = js_CodeSpec[op].format & JOF_GNAME;
if (global)
obj = obj->getGlobal();
obj = &obj->global();
Value rval;
@ -3552,8 +3546,8 @@ BEGIN_CASE(JSOP_CALLNAME)
} else {
Shape *shape = (Shape *)prop;
JSObject *normalized = obj;
if (normalized->getClass() == &WithClass && !shape->hasDefaultGetter())
normalized = js_UnwrapWithObject(cx, normalized);
if (normalized->isWith() && !shape->hasDefaultGetter())
normalized = &normalized->asWith().object();
NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval);
}
@ -3632,7 +3626,7 @@ BEGIN_CASE(JSOP_REGEXP)
* bytecode at pc.
*/
jsatomid index = GET_FULL_INDEX(0);
JSObject *proto = regs.fp()->scopeChain().getGlobal()->getOrCreateRegExpPrototype(cx);
JSObject *proto = regs.fp()->scopeChain().global().getOrCreateRegExpPrototype(cx);
if (!proto)
goto error;
JSObject *obj = js_CloneRegExpObject(cx, script->getRegExp(index), proto);
@ -5102,7 +5096,7 @@ BEGIN_CASE(JSOP_GETFUNNS)
JS_ASSERT(!script->strictModeCode);
Value rval;
if (!cx->fp()->scopeChain().getGlobal()->getFunctionNamespace(cx, &rval))
if (!cx->fp()->scopeChain().global().getFunctionNamespace(cx, &rval))
goto error;
PUSH_COPY(rval);
}
@ -5115,26 +5109,26 @@ BEGIN_CASE(JSOP_ENTERLET1)
{
JSObject *obj;
LOAD_OBJECT(0, obj);
JS_ASSERT(obj->isStaticBlock());
JS_ASSERT(regs.fp()->maybeBlockChain() == obj->staticBlockScopeChain());
StaticBlockObject &blockObj = obj->asStaticBlock();
JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
if (op == JSOP_ENTERBLOCK) {
JS_ASSERT(regs.fp()->base() + OBJ_BLOCK_DEPTH(cx, obj) == regs.sp);
Value *vp = regs.sp + OBJ_BLOCK_COUNT(cx, obj);
JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
Value *vp = regs.sp + blockObj.slotCount();
JS_ASSERT(regs.sp < vp);
JS_ASSERT(vp <= regs.fp()->slots() + script->nslots);
SetValueRangeToUndefined(regs.sp, vp);
regs.sp = vp;
} else if (op == JSOP_ENTERLET0) {
JS_ASSERT(regs.fp()->base() + OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
== regs.sp);
} else if (op == JSOP_ENTERLET1) {
JS_ASSERT(regs.fp()->base() + OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
== regs.sp - 1);
}
#ifdef DEBUG
JS_ASSERT(regs.fp()->maybeBlockChain() == obj->staticBlockScopeChain());
JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
/*
* The young end of fp->scopeChain may omit blocks if we haven't closed
@ -5145,19 +5139,18 @@ BEGIN_CASE(JSOP_ENTERLET1)
*/
JSObject *obj2 = &regs.fp()->scopeChain();
while (obj2->isWith())
obj2 = obj2->internalScopeChain();
obj2 = &obj2->asWith().enclosingScope();
if (obj2->isBlock() &&
obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, regs.fp()))
{
JSObject *youngestProto = obj2->getProto();
JS_ASSERT(youngestProto->isStaticBlock());
JSObject *parent = obj;
while ((parent = parent->scopeChain()) != youngestProto)
StaticBlockObject &youngestProto = obj2->asClonedBlock().staticBlock();
StaticBlockObject *parent = &blockObj;
while ((parent = parent->enclosingBlock()) != &youngestProto)
JS_ASSERT(parent);
}
#endif
regs.fp()->setBlockChain(obj);
regs.fp()->setBlockChain(&blockObj);
}
END_CASE(JSOP_ENTERBLOCK)
@ -5165,33 +5158,29 @@ BEGIN_CASE(JSOP_LEAVEBLOCK)
BEGIN_CASE(JSOP_LEAVEFORLETIN)
BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
{
JS_ASSERT(regs.fp()->blockChain().isStaticBlock());
DebugOnly<uintN> blockDepth = OBJ_BLOCK_DEPTH(cx, &regs.fp()->blockChain());
JS_ASSERT(blockDepth <= StackDepth(script));
StaticBlockObject &blockObj = regs.fp()->blockChain();
JS_ASSERT(blockObj.stackDepth() <= StackDepth(script));
/*
* If we're about to leave the dynamic scope of a block that has been
* cloned onto fp->scopeChain, clear its private data, move its locals from
* the stack into the clone, and pop it off the chain.
*/
JSObject &obj = regs.fp()->scopeChain();
if (obj.getProto() == &regs.fp()->blockChain()) {
JS_ASSERT(obj.isClonedBlock());
if (!js_PutBlockObject(cx, JS_TRUE))
goto error;
}
JSObject &scope = regs.fp()->scopeChain();
if (scope.getProto() == &blockObj && !scope.asClonedBlock().put(cx, JS_TRUE))
goto error;
regs.fp()->setBlockChain(regs.fp()->blockChain().staticBlockScopeChain());
regs.fp()->setBlockChain(blockObj.enclosingBlock());
if (op == JSOP_LEAVEBLOCK) {
/* Pop the block's slots. */
regs.sp -= GET_UINT16(regs.pc);
JS_ASSERT(regs.fp()->base() + blockDepth == regs.sp);
JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
} else if (op == JSOP_LEAVEBLOCKEXPR) {
/* Pop the block's slots maintaining the topmost expr. */
Value *vp = &regs.sp[-1];
regs.sp -= GET_UINT16(regs.pc);
JS_ASSERT(regs.fp()->base() + blockDepth == regs.sp - 1);
JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp - 1);
regs.sp[-1] = *vp;
} else {
/* Another op will pop; nothing to do here. */

View File

@ -324,13 +324,13 @@ class InterpreterFrames {
* fp->sp on return to stackDepth.
*/
extern bool
UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind);
UnwindScope(JSContext *cx, uint32_t stackDepth, JSBool normalUnwind);
extern bool
OnUnknownMethod(JSContext *cx, js::Value *vp);
extern bool
IsActiveWithOrBlock(JSContext *cx, JSObject &obj, int stackDepth);
IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth);
/************************************************************************/

View File

@ -1278,7 +1278,7 @@ js_NewGenerator(JSContext *cx)
JS_ASSERT(stackfp->base() == cx->regs().sp);
JS_ASSERT(stackfp->actualArgs() <= stackfp->formalArgs());
GlobalObject *global = stackfp->scopeChain().getGlobal();
GlobalObject *global = &stackfp->scopeChain().global();
JSObject *proto = global->getOrCreateGeneratorPrototype(cx);
if (!proto)
return NULL;
@ -1622,7 +1622,7 @@ js_InitIteratorClasses(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
/*
* Bail if Iterator has already been initialized. We test for Iterator

View File

@ -1012,12 +1012,12 @@ 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();
GlobalObject *global = &obj->asGlobal();
JSObject *numberProto = global->createBlankPrototype(cx, &NumberClass);
if (!numberProto)
return NULL;
numberProto->asNumber()->setPrimitiveValue(0);
numberProto->asNumber().setPrimitiveValue(0);
JSFunction *ctor = global->createConstructor(cx, Number, &NumberClass,
CLASS_ATOM(cx, Number), 1);

View File

@ -948,7 +948,7 @@ static void
AssertInnerizedScopeChain(JSContext *cx, JSObject &scopeobj)
{
#ifdef DEBUG
for (JSObject *o = &scopeobj; o; o = o->scopeChain()) {
for (JSObject *o = &scopeobj; o; o = o->enclosingScope()) {
if (JSObjectOp op = o->getClass()->ext.innerObject)
JS_ASSERT(op(cx, o) == o);
}
@ -1133,7 +1133,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
JS_ASSERT((evalType == INDIRECT_EVAL) == (caller == NULL));
AssertInnerizedScopeChain(cx, scopeobj);
if (!scopeobj.getGlobal()->isRuntimeCodeGenEnabled(cx)) {
if (!scopeobj.global().isRuntimeCodeGenEnabled(cx)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_EVAL);
return false;
}
@ -1175,7 +1175,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
JS_ASSERT(callerPC && JSOp(*callerPC) == JSOP_EVAL);
#endif
} else {
JS_ASSERT(args.callee().getGlobal() == &scopeobj);
JS_ASSERT(args.callee().global() == scopeobj);
staticLevel = 0;
/* Use the global as 'this', modulo outerization. */
@ -1305,7 +1305,7 @@ eval(JSContext *cx, uintN argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return WarnOnTooManyArgs(cx, args) &&
EvalKernel(cx, args, INDIRECT_EVAL, NULL, *args.callee().getGlobal());
EvalKernel(cx, args, INDIRECT_EVAL, NULL, args.callee().global());
}
bool
@ -1332,7 +1332,7 @@ DirectEval(JSContext *cx, const CallArgs &args)
bool
IsBuiltinEvalForScope(JSObject *scopeChain, const Value &v)
{
return scopeChain->getGlobal()->getOriginalEval() == v;
return scopeChain->global().getOriginalEval() == v;
}
bool
@ -2612,7 +2612,7 @@ obj_create(JSContext *cx, uintN 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, vp->toObject().getGlobal());
JSObject *obj = NewObjectWithGivenProto(cx, &ObjectClass, proto, &vp->toObject().global());
if (!obj)
return JS_FALSE;
vp->setObject(*obj); /* Root and prepare for eventual return. */
@ -3003,7 +3003,7 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
NewObjectCache::EntryIndex entry = -1;
if (parent->isGlobal() && protoKey != JSProto_Null) {
if (cache.lookupGlobal(clasp, parent->asGlobal(), kind, &entry))
if (cache.lookupGlobal(clasp, &parent->asGlobal(), kind, &entry))
return cache.newObjectFromHit(cx, entry);
}
@ -3021,7 +3021,7 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
return NULL;
if (entry != -1 && !obj->hasDynamicSlots())
cache.fillGlobal(entry, clasp, parent->asGlobal(), kind, obj);
cache.fillGlobal(entry, clasp, &parent->asGlobal(), kind, obj);
return obj;
}
@ -3276,457 +3276,6 @@ js_InferFlags(JSContext *cx, uintN defaultFlags)
return flags;
}
/*
* ObjectOps and Class for with-statement stack objects.
*/
static JSBool
with_LookupGeneric(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp)
{
/* Fixes bug 463997 */
uintN flags = cx->resolveFlags;
if (flags == RESOLVE_INFER)
flags = js_InferFlags(cx, flags);
flags |= JSRESOLVE_WITH;
JSAutoResolveFlags rf(cx, flags);
return obj->getProto()->lookupGeneric(cx, id, objp, propp);
}
static JSBool
with_LookupProperty(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp, JSProperty **propp)
{
return with_LookupGeneric(cx, obj, ATOM_TO_JSID(name), objp, propp);
}
static JSBool
with_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
JSProperty **propp)
{
jsid id;
if (!IndexToId(cx, index, &id))
return false;
return with_LookupGeneric(cx, obj, id, objp, propp);
}
static JSBool
with_LookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, JSProperty **propp)
{
return with_LookupGeneric(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
}
static JSBool
with_GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
{
return obj->getProto()->getGeneric(cx, id, vp);
}
static JSBool
with_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp)
{
return with_GetGeneric(cx, obj, receiver, ATOM_TO_JSID(name), vp);
}
static JSBool
with_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp)
{
jsid id;
if (!IndexToId(cx, index, &id))
return false;
return with_GetGeneric(cx, obj, receiver, id, vp);
}
static JSBool
with_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
{
return with_GetGeneric(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
}
static JSBool
with_SetGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
{
return obj->getProto()->setGeneric(cx, id, vp, strict);
}
static JSBool
with_SetProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
{
return obj->getProto()->setProperty(cx, name, vp, strict);
}
static JSBool
with_SetElement(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict)
{
return obj->getProto()->setElement(cx, index, vp, strict);
}
static JSBool
with_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
{
return obj->getProto()->setSpecial(cx, sid, vp, strict);
}
static JSBool
with_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
{
return obj->getProto()->getGenericAttributes(cx, id, attrsp);
}
static JSBool
with_GetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
{
return obj->getProto()->getPropertyAttributes(cx, name, attrsp);
}
static JSBool
with_GetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, uintN *attrsp)
{
return obj->getProto()->getElementAttributes(cx, index, attrsp);
}
static JSBool
with_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
{
return obj->getProto()->getSpecialAttributes(cx, sid, attrsp);
}
static JSBool
with_SetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
{
return obj->getProto()->setGenericAttributes(cx, id, attrsp);
}
static JSBool
with_SetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
{
return obj->getProto()->setPropertyAttributes(cx, name, attrsp);
}
static JSBool
with_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, uintN *attrsp)
{
return obj->getProto()->setElementAttributes(cx, index, attrsp);
}
static JSBool
with_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
{
return obj->getProto()->setSpecialAttributes(cx, sid, attrsp);
}
static JSBool
with_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
{
return obj->getProto()->deleteGeneric(cx, id, rval, strict);
}
static JSBool
with_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
return obj->getProto()->deleteProperty(cx, name, rval, strict);
}
static JSBool
with_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict)
{
return obj->getProto()->deleteElement(cx, index, rval, strict);
}
static JSBool
with_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
{
return obj->getProto()->deleteSpecial(cx, sid, rval, strict);
}
static JSBool
with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
Value *statep, jsid *idp)
{
return obj->getProto()->enumerate(cx, enum_op, statep, idp);
}
static JSType
with_TypeOf(JSContext *cx, JSObject *obj)
{
return JSTYPE_OBJECT;
}
static JSObject *
with_ThisObject(JSContext *cx, JSObject *obj)
{
return obj->getWithThis();
}
Class js::WithClass = {
"With",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(3) | JSCLASS_IS_ANONYMOUS,
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
NULL, /* finalize */
NULL, /* reserved */
NULL, /* checkAccess */
NULL, /* call */
NULL, /* construct */
NULL, /* xdrObject */
NULL, /* hasInstance */
NULL, /* trace */
JS_NULL_CLASS_EXT,
{
with_LookupGeneric,
with_LookupProperty,
with_LookupElement,
with_LookupSpecial,
NULL, /* defineGeneric */
NULL, /* defineProperty */
NULL, /* defineElement */
NULL, /* defineSpecial */
with_GetGeneric,
with_GetProperty,
with_GetElement,
NULL, /* getElementIfPresent */
with_GetSpecial,
with_SetGeneric,
with_SetProperty,
with_SetElement,
with_SetSpecial,
with_GetGenericAttributes,
with_GetPropertyAttributes,
with_GetElementAttributes,
with_GetSpecialAttributes,
with_SetGenericAttributes,
with_SetPropertyAttributes,
with_SetElementAttributes,
with_SetSpecialAttributes,
with_DeleteGeneric,
with_DeleteProperty,
with_DeleteElement,
with_DeleteSpecial,
with_Enumerate,
with_TypeOf,
NULL, /* fix */
with_ThisObject,
NULL, /* clear */
}
};
static const gc::AllocKind WITH_FINALIZE_KIND = gc::FINALIZE_OBJECT4;
JS_REQUIRES_STACK JSObject *
js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
{
JSObject *obj;
RootedVarTypeObject type(cx);
type = proto->getNewType(cx);
if (!type)
return NULL;
StackFrame *priv = js_FloatingFrameIfGenerator(cx, cx->fp());
RootedVarShape emptyWithShape(cx);
emptyWithShape = EmptyShape::getInitialShape(cx, &WithClass, proto,
parent->getGlobal(),
WITH_FINALIZE_KIND);
if (!emptyWithShape)
return NULL;
obj = JSObject::create(cx, WITH_FINALIZE_KIND, emptyWithShape, type, NULL);
if (!obj)
return NULL;
OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
if (!obj->setInternalScopeChain(cx, parent))
return NULL;
obj->setPrivate(priv);
JSObject *thisp = proto->thisObject(cx);
if (!thisp)
return NULL;
assertSameCompartment(cx, obj, thisp);
obj->setWithThis(thisp);
return obj;
}
static const uint32_t BLOCK_RESERVED_SLOTS = 2;
static const gc::AllocKind BLOCK_FINALIZE_KIND = gc::FINALIZE_OBJECT4;
JSObject *
js_NewBlockObject(JSContext *cx)
{
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
RootedVarShape emptyBlockShape(cx);
emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockClass, NULL, NULL,
BLOCK_FINALIZE_KIND);
if (!emptyBlockShape)
return NULL;
return JSObject::create(cx, FINALIZE_OBJECT4, emptyBlockShape, type, NULL);
}
JSObject *
js_CloneBlockObject(JSContext *cx, JSObject *proto, StackFrame *fp)
{
JS_ASSERT(proto->isStaticBlock());
RootedVarTypeObject type(cx);
type = proto->getNewType(cx);
if (!type)
return NULL;
HeapValue *slots;
if (!PreallocateObjectDynamicSlots(cx, proto->lastProperty(), &slots))
return NULL;
RootedVarShape shape(cx);
shape = proto->lastProperty();
JSObject *clone = JSObject::create(cx, BLOCK_FINALIZE_KIND,
shape, type, slots);
if (!clone)
return NULL;
/* Set the parent if necessary, as for call objects. */
JSObject *global = fp->scopeChain().getGlobal();
if (global != clone->getParent()) {
JS_ASSERT(clone->getParent() == NULL);
if (!clone->setParent(cx, global))
return NULL;
}
JS_ASSERT(!clone->inDictionaryMode());
JS_ASSERT(clone->isClonedBlock());
JS_ASSERT(clone->slotSpan() >= OBJ_BLOCK_COUNT(cx, proto) + BLOCK_RESERVED_SLOTS);
clone->setPrivate(js_FloatingFrameIfGenerator(cx, fp));
clone->setSlot(JSSLOT_BLOCK_DEPTH, proto->getSlot(JSSLOT_BLOCK_DEPTH));
if (clone->lastProperty()->extensibleParents() && !clone->generateOwnShape(cx))
return NULL;
return clone;
}
JS_REQUIRES_STACK JSBool
js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
{
StackFrame *const fp = cx->fp();
JSObject *obj = &fp->scopeChain();
JS_ASSERT(obj->isClonedBlock());
JS_ASSERT(obj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()));
/* Block objects should have all reserved slots allocated early. */
uintN count = OBJ_BLOCK_COUNT(cx, obj);
JS_ASSERT(obj->slotSpan() >= JSSLOT_BLOCK_DEPTH + 1 + count);
/* The block and its locals must be on the current stack for GC safety. */
uintN depth = OBJ_BLOCK_DEPTH(cx, obj);
JS_ASSERT(depth <= size_t(cx->regs().sp - fp->base()));
JS_ASSERT(count <= size_t(cx->regs().sp - fp->base() - depth));
/* See comments in CheckDestructuring in frontend/Parser.cpp. */
JS_ASSERT(count >= 1);
if (normalUnwind) {
uintN slot = JSSLOT_BLOCK_FIRST_FREE_SLOT;
depth += fp->numFixed();
obj->copySlotRange(slot, fp->slots() + depth, count);
}
/* We must clear the private slot even with errors. */
obj->setPrivate(NULL);
fp->setScopeChainNoCallObj(*obj->internalScopeChain());
return normalUnwind;
}
static JSBool
block_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
/*
* Block objects are never exposed to script, and the engine handles them
* with care. So unlike other getters, this one can assert (rather than
* check) certain invariants about obj.
*/
JS_ASSERT(obj->isClonedBlock());
uintN index = (uintN) JSID_TO_INT(id);
JS_ASSERT(index < OBJ_BLOCK_COUNT(cx, obj));
StackFrame *fp = (StackFrame *) obj->getPrivate();
if (fp) {
fp = js_LiveFrameIfGenerator(fp);
index += fp->numFixed() + OBJ_BLOCK_DEPTH(cx, obj);
JS_ASSERT(index < fp->numSlots());
*vp = fp->slots()[index];
return true;
}
/* Values are in slots immediately following the class-reserved ones. */
JS_ASSERT(obj->getSlot(JSSLOT_FREE(&BlockClass) + index) == *vp);
return true;
}
static JSBool
block_setProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
{
JS_ASSERT(obj->isClonedBlock());
uintN index = (uintN) JSID_TO_INT(id);
JS_ASSERT(index < OBJ_BLOCK_COUNT(cx, obj));
StackFrame *fp = (StackFrame *) obj->getPrivate();
if (fp) {
fp = js_LiveFrameIfGenerator(fp);
index += fp->numFixed() + OBJ_BLOCK_DEPTH(cx, obj);
JS_ASSERT(index < fp->numSlots());
fp->slots()[index] = *vp;
return true;
}
/*
* The value in *vp will be written back to the slot in obj that was
* allocated when this let binding was defined.
*/
return true;
}
const Shape *
JSObject::defineBlockVariable(JSContext *cx, jsid id, intN index, bool *redeclared)
{
JS_ASSERT(isStaticBlock());
*redeclared = false;
RootedVarObject self(cx, this);
/* Inline JSObject::addProperty in order to trap the redefinition case. */
Shape **spp;
Shape *shape = Shape::search(cx, lastProperty(), id, &spp, true);
if (shape) {
*redeclared = true;
return NULL;
}
/*
* Don't convert this object to dictionary mode so that we can clone the
* block's shape later.
*/
uint32_t slot = JSSLOT_FREE(&BlockClass) + index;
shape = self->addPropertyInternal(cx, id, block_getProperty, block_setProperty,
slot, JSPROP_ENUMERATE | JSPROP_PERMANENT,
Shape::HAS_SHORTID, index, spp,
/* allowDictionary = */ false);
if (!shape)
return NULL;
return shape;
}
JSBool
JSObject::nonNativeSetProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict)
{
@ -4128,153 +3677,6 @@ JSObject::swap(JSContext *cx, JSObject *other)
return true;
}
#if JS_HAS_XDR
#define NO_PARENT_INDEX UINT32_MAX
uint32_t
FindObjectIndex(JSObjectArray *array, JSObject *obj)
{
size_t i;
if (array) {
i = array->length;
do {
if (array->vector[--i] == obj)
return i;
} while (i != 0);
}
return NO_PARENT_INDEX;
}
JSBool
js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
{
JSContext *cx;
uint32_t parentId;
JSObject *obj, *parent;
uintN depth, count;
uint32_t depthAndCount;
const Shape *shape;
cx = xdr->cx;
#ifdef __GNUC__
obj = NULL; /* quell GCC overwarning */
#endif
if (xdr->mode == JSXDR_ENCODE) {
obj = *objp;
parent = obj->staticBlockScopeChain();
parentId = JSScript::isValidOffset(xdr->script->objectsOffset)
? FindObjectIndex(xdr->script->objects(), parent)
: NO_PARENT_INDEX;
depth = uint16_t(OBJ_BLOCK_DEPTH(cx, obj));
count = uint16_t(OBJ_BLOCK_COUNT(cx, obj));
depthAndCount = uint32_t(depth << 16) | count;
}
#ifdef __GNUC__ /* suppress bogus gcc warnings */
else count = 0;
#endif
/* First, XDR the parent atomid. */
if (!JS_XDRUint32(xdr, &parentId))
return JS_FALSE;
if (xdr->mode == JSXDR_DECODE) {
obj = js_NewBlockObject(cx);
if (!obj)
return JS_FALSE;
*objp = obj;
/*
* If there's a parent id, then get the parent out of our script's
* object array. We know that we XDR block object in outer-to-inner
* order, which means that getting the parent now will work.
*/
if (parentId == NO_PARENT_INDEX)
parent = NULL;
else
parent = xdr->script->getObject(parentId);
obj->setStaticBlockScopeChain(parent);
}
if (!JS_XDRUint32(xdr, &depthAndCount))
return false;
if (xdr->mode == JSXDR_DECODE) {
depth = uint16_t(depthAndCount >> 16);
count = uint16_t(depthAndCount);
obj->setSlot(JSSLOT_BLOCK_DEPTH, Value(Int32Value(depth)));
/*
* XDR the block object's properties. We know that there are 'count'
* properties to XDR, stored as id/shortid pairs.
*/
for (uintN i = 0; i < count; i++) {
JSAtom *atom;
/* XDR the real id. */
if (!js_XDRAtom(xdr, &atom))
return false;
bool redeclared;
if (!obj->defineBlockVariable(cx, ATOM_TO_JSID(atom), i, &redeclared)) {
JS_ASSERT(!redeclared);
return false;
}
}
} else {
AutoShapeVector shapes(cx);
shapes.growBy(count);
for (Shape::Range r(obj->lastProperty()); !r.empty(); r.popFront()) {
shape = &r.front();
shapes[shape->shortid()] = shape;
}
/*
* XDR the block object's properties. We know that there are 'count'
* properties to XDR, stored as id/shortid pairs.
*/
for (uintN i = 0; i < count; i++) {
shape = shapes[i];
JS_ASSERT(shape->getter() == block_getProperty);
jsid propid = shape->propid();
JS_ASSERT(JSID_IS_ATOM(propid));
JSAtom *atom = JSID_TO_ATOM(propid);
#ifdef DEBUG
uint16_t shortid = uint16_t(shape->shortid());
JS_ASSERT(shortid == i);
#endif
/* XDR the real id. */
if (!js_XDRAtom(xdr, &atom))
return false;
}
}
return true;
}
#endif
Class js::BlockClass = {
"Block",
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(BLOCK_RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS,
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub
};
static bool
DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
const Value &v, uint32_t attrs, bool &named)
@ -5030,7 +4432,7 @@ js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
{
RootObject objRoot(cx, &obj);
obj = obj->getGlobal();
obj = &obj->global();
if (!obj->isGlobal()) {
*objp = NULL;
return true;
@ -5074,7 +4476,7 @@ js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
RootedVarObject obj(cx);
if (start) {
obj = start->getGlobal();
obj = &start->global();
OBJ_TO_INNER_OBJECT(cx, *obj.address());
} else {
obj = GetGlobalForScopeChain(cx);
@ -5286,7 +4688,7 @@ js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id)
* may gain such properties via eval introducing new vars; see bug 490364.
*/
if (obj->isCall()) {
while ((obj = obj->scopeChain()) != NULL) {
while ((obj = obj->enclosingScope()) != NULL) {
if (!PurgeProtoChain(cx, obj, id))
return false;
}
@ -5724,13 +5126,13 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
* the actual behavior even if the id could be found on the scope chain
* before the global object.
*/
scopeChain = scopeChain->getGlobal();
scopeChain = &scopeChain->global();
}
/* Scan entries on the scope chain that we can cache across. */
entry = JS_NO_PROP_CACHE_FILL;
obj = scopeChain;
parent = obj->scopeChain();
parent = obj->enclosingScope();
for (scopeIndex = 0;
parent
? IsCacheableNonGlobalScope(obj)
@ -5776,7 +5178,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
goto out;
}
obj = parent;
parent = obj->scopeChain();
parent = obj->enclosingScope();
}
for (;;) {
@ -5791,7 +5193,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
* We conservatively assume that a resolve hook could mutate the scope
* chain during JSObject::lookupGeneric. So we read parent here again.
*/
parent = obj->scopeChain();
parent = obj->enclosingScope();
if (!parent) {
pobj = NULL;
break;
@ -5825,7 +5227,7 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
* This function should not be called for a global object or from the
* trace and should have a valid cache entry for native scopeChain.
*/
JS_ASSERT(scopeChain->scopeChain() != NULL);
JS_ASSERT(scopeChain->enclosingScope() != NULL);
JSObject *obj = scopeChain;
@ -5850,14 +5252,14 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
JS_ASSERT(obj->isGlobal());
return obj;
}
JS_ASSERT_IF(obj->isInternalScope(), pobj->getClass() == obj->getClass());
JS_ASSERT_IF(obj->isScope(), pobj->getClass() == obj->getClass());
DebugOnly<PropertyCacheEntry*> entry =
JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, (Shape *) prop);
JS_ASSERT(entry);
return obj;
}
JSObject *parent = obj->scopeChain();
JSObject *parent = obj->enclosingScope();
if (!parent)
return obj;
obj = parent;
@ -5877,7 +5279,7 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
* chain during JSObject::lookupGeneric. So we must check if parent is
* not null here even if it wasn't before the lookup.
*/
JSObject *parent = obj->scopeChain();
JSObject *parent = obj->enclosingScope();
if (!parent)
break;
obj = parent;
@ -6863,7 +6265,7 @@ js_GetClassPrototype(JSContext *cx, JSObject *scopeobj, JSProtoKey protoKey,
if (protoKey != JSProto_Null) {
GlobalObject *global;
if (scopeobj) {
global = scopeobj->getGlobal();
global = &scopeobj->global();
} else {
global = GetCurrentGlobal(cx);
if (!global) {

View File

@ -343,13 +343,20 @@ extern Class WithClass;
extern Class XMLFilterClass;
class ArgumentsObject;
class BlockObject;
class BooleanObject;
class ClonedBlockObject;
class DeclEnvObject;
class GlobalObject;
class NestedScopeObject;
class NormalArgumentsObject;
class NumberObject;
class ScopeObject;
class StaticBlockObject;
class StrictArgumentsObject;
class StringObject;
class RegExpObject;
class WithObject;
/*
* Header structure for object element arrays. This structure is immediately
@ -775,10 +782,8 @@ struct JSObject : js::gc::Cell
inline void nativeSetSlot(uintN slot, const js::Value &value);
inline void nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value);
inline js::Value getReservedSlot(uintN index) const;
inline const js::Value &getReservedSlot(uintN index) const;
inline js::HeapValue &getReservedSlotRef(uintN index);
/* Call this only after the appropriate ensure{Class,Instance}ReservedSlots call. */
inline void setReservedSlot(uintN index, const js::Value &v);
/* For slots which are known to always be fixed, due to the way they are allocated. */
@ -873,11 +878,11 @@ struct JSObject : js::gc::Cell
*
* Except for the non-script-accessible builtins, the global with which an
* object is associated can be reached by following parent links to that
* global (see getGlobal()).
* global (see global()).
*
* The scope chain of an object is the link in the search path when a
* script does a name lookup on a scope object. For JS internal scope
* objects --- Call, Block, DeclEnv and With --- the chain is stored in
* objects --- Call, DeclEnv and block --- the chain is stored in
* the first fixed slot of the object, and the object's parent is the
* associated global. For other scope objects, the chain is stored in the
* object's parent.
@ -893,30 +898,14 @@ struct JSObject : js::gc::Cell
inline JSObject *getParent() const;
bool setParent(JSContext *cx, JSObject *newParent);
/* Get the scope chain of an arbitrary scope object. */
inline JSObject *scopeChain() const;
inline bool isGlobal() const;
inline js::GlobalObject *asGlobal();
inline js::GlobalObject *getGlobal() const;
inline bool isInternalScope() const;
/* Access the scope chain of an internal scope object. */
inline JSObject *internalScopeChain() const;
inline bool setInternalScopeChain(JSContext *cx, JSObject *obj);
static inline size_t offsetOfInternalScopeChain();
/*
* Access the scope chain of a static block object. These do not appear
* on scope chains but mirror their structure, and can have a NULL
* scope chain.
* Get the enclosing scope of an object. When called on non-scope object,
* this will just be the global (the name "enclosing scope" still applies
* in this situation because non-scope objects can be on the scope chain).
*/
inline JSObject *staticBlockScopeChain() const;
inline void setStaticBlockScopeChain(JSObject *obj);
inline JSObject *enclosingScope();
/* Common fixed slot for the scope chain of internal scope objects. */
static const uint32_t SCOPE_CHAIN_SLOT = 0;
inline js::GlobalObject &global() const;
/* Private data accessors. */
@ -981,12 +970,6 @@ struct JSObject : js::gc::Cell
return getFixedSlotOffset(JSSLOT_PRIMITIVE_THIS);
}
public:
inline js::BooleanObject *asBoolean();
inline js::NumberObject *asNumber();
inline js::StringObject *asString();
inline js::RegExpObject *asRegExp();
/* Accessors for elements. */
js::ObjectElements *getElementsHeader() const {
@ -1079,14 +1062,6 @@ struct JSObject : js::gc::Cell
inline uint32_t arrayBufferByteLength();
inline uint8_t * arrayBufferDataOffset();
public:
inline js::ArgumentsObject *asArguments();
inline js::NormalArgumentsObject *asNormalArguments();
inline js::StrictArgumentsObject *asStrictArguments();
public:
inline js::CallObject &asCall();
public:
/*
* Date-specific getters and setters.
@ -1178,12 +1153,6 @@ struct JSObject : js::gc::Cell
*/
inline js::Wrapper *getWrapperHandler() const;
/*
* With object-specific getters and setters.
*/
inline JSObject *getWithThis() const;
inline void setWithThis(JSObject *thisp);
/*
* Back to generic stuff.
*/
@ -1220,6 +1189,7 @@ struct JSObject : js::gc::Cell
private:
js::Shape *getChildProperty(JSContext *cx, js::Shape *parent, js::StackShape &child);
protected:
/*
* Internal helper that adds a shape not yet mapped by this object.
*
@ -1233,6 +1203,7 @@ struct JSObject : js::gc::Cell
uintN flags, intN shortid, js::Shape **spp,
bool allowDictionary);
private:
bool toDictionaryMode(JSContext *cx);
struct TradeGutsReserved;
@ -1345,46 +1316,6 @@ struct JSObject : js::gc::Cell
bool swap(JSContext *cx, JSObject *other);
const js::Shape *defineBlockVariable(JSContext *cx, jsid id, intN index, bool *redeclared);
inline bool isArguments() const;
inline bool isArrayBuffer() const;
inline bool isNormalArguments() const;
inline bool isStrictArguments() const;
inline bool isArray() const;
inline bool isDenseArray() const;
inline bool isSlowArray() const;
inline bool isNumber() const;
inline bool isBoolean() const;
inline bool isString() const;
inline bool isPrimitive() const;
inline bool isDate() const;
inline bool isFunction() const;
inline bool isObject() const;
inline bool isWith() const;
inline bool isBlock() const;
inline bool isStaticBlock() const;
inline bool isClonedBlock() const;
inline bool isCall() const;
inline bool isDeclEnv() const;
inline bool isRegExp() const;
inline bool isScript() const;
inline bool isGenerator() const;
inline bool isIterator() const;
inline bool isStopIteration() const;
inline bool isError() const;
inline bool isXML() const;
inline bool isNamespace() const;
inline bool isWeakMap() const;
inline bool isFunctionProxy() const;
inline bool isProxy() const;
inline bool isXMLId() const;
inline bool isQName() const;
inline bool isWrapper() const;
inline bool isCrossCompartmentWrapper() const;
inline void initArrayClass();
static inline void writeBarrierPre(JSObject *obj);
@ -1392,6 +1323,99 @@ struct JSObject : js::gc::Cell
inline void privateWriteBarrierPre(void **oldval);
inline void privateWriteBarrierPost(void **oldval);
/*
* In addition to the generic object interface provided by JSObject,
* specific types of objects may provide additional operations. To access,
* these addition operations, callers should use the pattern:
*
* if (obj.isX()) {
* XObject &x = obj.asX();
* x.foo();
* }
*
* These XObject classes form a hierarchy. For example, for a cloned block
* object, the following predicates are true: isClonedBlock, isBlock,
* isNestedScope and isScope. Each of these has a respective class that
* derives and adds operations.
*
* A class XObject is defined in a vm/XObject{.h, .cpp, -inl.h} file
* triplet (along with any class YObject that derives XObject).
*
* Note that X represents a low-level representation and does not query the
* [[Class]] property of object defined by the spec (for this, see
* js::ObjectClassIs).
*
* SpiderMonkey has not been completely switched to the isX/asX/XObject
* pattern so in some cases there is no XObject class and the engine
* instead pokes directly at reserved slots and getPrivate. In such cases,
* consider adding the missing XObject class.
*/
/* Direct subtypes of JSObject: */
inline bool isArguments() const;
inline bool isArrayBuffer() const;
inline bool isArray() const;
inline bool isDate() const;
inline bool isDenseArray() const;
inline bool isError() const;
inline bool isFunction() const;
inline bool isGenerator() const;
inline bool isGlobal() const;
inline bool isIterator() const;
inline bool isNamespace() const;
inline bool isObject() const;
inline bool isQName() const;
inline bool isPrimitive() const;
inline bool isProxy() const;
inline bool isRegExp() const;
inline bool isScope() const;
inline bool isScript() const;
inline bool isSlowArray() const;
inline bool isStopIteration() const;
inline bool isWeakMap() const;
inline bool isXML() const;
inline bool isXMLId() const;
/* Subtypes of ScopeObject. */
inline bool isBlock() const;
inline bool isCall() const;
inline bool isDeclEnv() const;
inline bool isNestedScope() const;
inline bool isWith() const;
inline bool isClonedBlock() const;
inline bool isStaticBlock() const;
/* Subtypes of PrimitiveObject. */
inline bool isBoolean() const;
inline bool isNumber() const;
inline bool isString() const;
/* Subtypes of ArgumentsObject. */
inline bool isNormalArguments() const;
inline bool isStrictArguments() const;
/* Subtypes of Proxy. */
inline bool isWrapper() const;
inline bool isFunctionProxy() const;
inline bool isCrossCompartmentWrapper() const;
inline js::ArgumentsObject &asArguments();
inline js::BlockObject &asBlock();
inline js::BooleanObject &asBoolean();
inline js::CallObject &asCall();
inline js::ClonedBlockObject &asClonedBlock();
inline js::DeclEnvObject &asDeclEnv();
inline js::GlobalObject &asGlobal();
inline js::NestedScopeObject &asNestedScope();
inline js::NormalArgumentsObject &asNormalArguments();
inline js::NumberObject &asNumber();
inline js::RegExpObject &asRegExp();
inline js::ScopeObject &asScope();
inline js::StrictArgumentsObject &asStrictArguments();
inline js::StaticBlockObject &asStaticBlock();
inline js::StringObject &asString();
inline js::WithObject &asWith();
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; }
private:
@ -1484,66 +1508,6 @@ class ValueArray {
ValueArray(js::Value *v, size_t c) : array(v), length(c) {}
};
/*
* Block scope object macros. The slots reserved by BlockClass are:
*
* private StackFrame * active frame pointer or null
* JSSLOT_SCOPE_CHAIN JSObject * scope chain, as for other scopes
* JSSLOT_BLOCK_DEPTH int depth of block slots in frame
*
* After JSSLOT_BLOCK_DEPTH come one or more slots for the block locals.
*
* A With object is like a Block object, in that both have a reserved slot
* telling the stack depth of the relevant slots (the slot whose value is the
* object named in the with statement, the slots containing the block's local
* variables); and both have a private slot referring to the StackFrame in
* whose activation they were created (or null if the with or block object
* outlives the frame).
*/
static const uint32_t JSSLOT_BLOCK_DEPTH = 1;
static const uint32_t JSSLOT_BLOCK_FIRST_FREE_SLOT = JSSLOT_BLOCK_DEPTH + 1;
static const uint32_t JSSLOT_WITH_THIS = 2;
#define OBJ_BLOCK_COUNT(cx,obj) \
(obj)->propertyCount()
#define OBJ_BLOCK_DEPTH(cx,obj) \
(obj)->getFixedSlot(JSSLOT_BLOCK_DEPTH).toInt32()
#define OBJ_SET_BLOCK_DEPTH(cx,obj,depth) \
(obj)->setFixedSlot(JSSLOT_BLOCK_DEPTH, Value(Int32Value(depth)))
/*
* To make sure this slot is well-defined, always call js_NewWithObject to
* create a With object, don't call js_NewObject directly. When creating a
* With object that does not correspond to a stack slot, pass -1 for depth.
*
* When popping the stack across this object's "with" statement, client code
* must call withobj->setPrivate(NULL).
*/
extern JS_REQUIRES_STACK JSObject *
js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth);
inline JSObject *
js_UnwrapWithObject(JSContext *cx, JSObject *withobj);
/*
* Create a new block scope object not linked to any proto or parent object.
* Blocks are created by the compiler to reify let blocks and comprehensions.
* Only when dynamic scope is captured do they need to be cloned and spliced
* into an active scope chain.
*/
extern JSObject *
js_NewBlockObject(JSContext *cx);
extern JSObject *
js_CloneBlockObject(JSContext *cx, JSObject *proto, js::StackFrame *fp);
extern JS_REQUIRES_STACK JSBool
js_PutBlockObject(JSContext *cx, JSBool normalUnwind);
JSBool
js_XDRBlockObject(JSXDRState *xdr, JSObject **objp);
/* For manipulating JSContext::sharpObjectMap. */
#define SHARP_BIT ((jsatomid) 1)
#define BUSY_BIT ((jsatomid) 2)

View File

@ -44,29 +44,24 @@
#include <new>
#include "jsarray.h"
#include "jsbool.h"
#include "jscntxt.h"
#include "jsdate.h"
#include "jsfun.h"
#include "jsgcmark.h"
#include "jsiter.h"
#include "jslock.h"
#include "jsnum.h"
#include "jsobj.h"
#include "jsprobes.h"
#include "jspropertytree.h"
#include "jsproxy.h"
#include "jsscope.h"
#include "jsstr.h"
#include "jstypedarray.h"
#include "jsxml.h"
#include "jswrapper.h"
/* Headers included for inline implementations used by this header. */
#include "jsbool.h"
#include "jscntxt.h"
#include "jsnum.h"
#include "jsinferinlines.h"
#include "jsscopeinlines.h"
#include "jsscriptinlines.h"
#include "jsstr.h"
#include "gc/Barrier.h"
#include "js/TemplateLib.h"
#include "vm/GlobalObject.h"
@ -74,7 +69,9 @@
#include "jsatominlines.h"
#include "jsfuninlines.h"
#include "jsgcinlines.h"
#include "jsinferinlines.h"
#include "jsscopeinlines.h"
#include "jsscriptinlines.h"
#include "gc/Barrier-inl.h"
#include "vm/String-inl.h"
@ -288,53 +285,10 @@ JSObject::getParent() const
return lastProperty()->getObjectParent();
}
inline bool
JSObject::isInternalScope() const
{
return isCall() || isDeclEnv() || isBlock() || isWith();
}
inline JSObject *
JSObject::internalScopeChain() const
JSObject::enclosingScope()
{
JS_ASSERT(isInternalScope());
return &getFixedSlot(SCOPE_CHAIN_SLOT).toObject();
}
inline bool
JSObject::setInternalScopeChain(JSContext *cx, JSObject *obj)
{
JS_ASSERT(isInternalScope());
if (!obj->setDelegate(cx))
return false;
setFixedSlot(SCOPE_CHAIN_SLOT, JS::ObjectValue(*obj));
return true;
}
/*static*/ inline size_t
JSObject::offsetOfInternalScopeChain()
{
return getFixedSlotOffset(SCOPE_CHAIN_SLOT);
}
inline JSObject *
JSObject::scopeChain() const
{
return isInternalScope() ? internalScopeChain() : getParent();
}
inline JSObject *
JSObject::staticBlockScopeChain() const
{
JS_ASSERT(isStaticBlock());
return getFixedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
}
inline void
JSObject::setStaticBlockScopeChain(JSObject *obj)
{
JS_ASSERT(isStaticBlock());
setFixedSlot(SCOPE_CHAIN_SLOT, JS::ObjectOrNullValue(obj));
return isScope() ? &asScope().enclosingScope() : getParent();
}
/*
@ -458,7 +412,7 @@ JSObject::getRawSlots()
return slots;
}
inline js::Value
inline const js::Value &
JSObject::getReservedSlot(uintN index) const
{
JS_ASSERT(index < JSSLOT_FREE(getClass()));
@ -805,18 +759,6 @@ JSObject::setQNameLocalName(JSAtom *name)
setSlot(JSSLOT_QNAME_LOCAL_NAME, name ? js::StringValue(name) : js::UndefinedValue());
}
inline JSObject *
JSObject::getWithThis() const
{
return &getFixedSlot(JSSLOT_WITH_THIS).toObject();
}
inline void
JSObject::setWithThis(JSObject *thisp)
{
setFixedSlot(JSSLOT_WITH_THIS, js::ObjectValue(*thisp));
}
inline bool
JSObject::setSingletonType(JSContext *cx)
{
@ -947,31 +889,32 @@ inline bool JSObject::hasSpecialEquality() const
inline bool JSObject::isArguments() const { return isNormalArguments() || isStrictArguments(); }
inline bool JSObject::isArrayBuffer() const { return hasClass(&js::ArrayBufferClass); }
inline bool JSObject::isNormalArguments() const { return hasClass(&js::NormalArgumentsObjectClass); }
inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
inline bool JSObject::isNumber() const { return hasClass(&js::NumberClass); }
inline bool JSObject::isBoolean() const { return hasClass(&js::BooleanClass); }
inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
inline bool JSObject::isPrimitive() const { return isNumber() || isString() || isBoolean(); }
inline bool JSObject::isDate() const { return hasClass(&js::DateClass); }
inline bool JSObject::isFunction() const { return hasClass(&js::FunctionClass); }
inline bool JSObject::isObject() const { return hasClass(&js::ObjectClass); }
inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
inline bool JSObject::isBlock() const { return hasClass(&js::BlockClass); }
inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
inline bool JSObject::isClonedBlock() const { return isBlock() && !!getProto(); }
inline bool JSObject::isBoolean() const { return hasClass(&js::BooleanClass); }
inline bool JSObject::isCall() const { return hasClass(&js::CallClass); }
inline bool JSObject::isClonedBlock() const { return isBlock() && !!getProto(); }
inline bool JSObject::isDate() const { return hasClass(&js::DateClass); }
inline bool JSObject::isDeclEnv() const { return hasClass(&js::DeclEnvClass); }
inline bool JSObject::isRegExp() const { return hasClass(&js::RegExpClass); }
inline bool JSObject::isScript() const { return hasClass(&js::ScriptClass); }
inline bool JSObject::isError() const { return hasClass(&js::ErrorClass); }
inline bool JSObject::isFunction() const { return hasClass(&js::FunctionClass); }
inline bool JSObject::isFunctionProxy() const { return hasClass(&js::FunctionProxyClass); }
inline bool JSObject::isGenerator() const { return hasClass(&js::GeneratorClass); }
inline bool JSObject::isIterator() const { return hasClass(&js::IteratorClass); }
inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
inline bool JSObject::isError() const { return hasClass(&js::ErrorClass); }
inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
inline bool JSObject::isNamespace() const { return hasClass(&js::NamespaceClass); }
inline bool JSObject::isNestedScope() const { return isBlock() || isWith(); }
inline bool JSObject::isNormalArguments() const { return hasClass(&js::NormalArgumentsObjectClass); }
inline bool JSObject::isNumber() const { return hasClass(&js::NumberClass); }
inline bool JSObject::isObject() const { return hasClass(&js::ObjectClass); }
inline bool JSObject::isPrimitive() const { return isNumber() || isString() || isBoolean(); }
inline bool JSObject::isRegExp() const { return hasClass(&js::RegExpClass); }
inline bool JSObject::isScope() const { return isCall() || isDeclEnv() || isNestedScope(); }
inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
inline bool JSObject::isFunctionProxy() const { return hasClass(&js::FunctionProxyClass); }
inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
inline bool JSObject::isArray() const
{
@ -1432,8 +1375,8 @@ JSObject::isWrapper() const
return js::IsWrapper(this);
}
inline js::GlobalObject *
JSObject::getGlobal() const
inline js::GlobalObject &
JSObject::global() const
{
JSObject *obj = const_cast<JSObject *>(this);
while (JSObject *parent = obj->getParent())
@ -1447,13 +1390,6 @@ js_IsCallable(const js::Value &v)
return v.isObject() && v.toObject().isCallable();
}
inline JSObject *
js_UnwrapWithObject(JSContext *cx, JSObject *withobj)
{
JS_ASSERT(withobj->isWith());
return withobj->getProto();
}
namespace js {
inline void
@ -1773,7 +1709,7 @@ inline GlobalObject *
GetCurrentGlobal(JSContext *cx)
{
JSObject *scopeChain = (cx->hasfp()) ? &cx->fp()->scopeChain() : cx->globalObject;
return scopeChain ? scopeChain->getGlobal() : NULL;
return scopeChain ? &scopeChain->global() : NULL;
}
bool

View File

@ -228,7 +228,7 @@ NumBlockSlots(JSScript *script, jsbytecode *pc)
JSObject *obj = NULL;
GET_OBJECT_FROM_BYTECODE(script, pc, 0, obj);
return OBJ_BLOCK_COUNT(NULL, obj);
return obj->asStaticBlock().slotCount();
}
uintN
@ -494,10 +494,8 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
if (!JSVAL_IS_PRIMITIVE(v)) {
JSObject *obj = JSVAL_TO_OBJECT(v);
Class *clasp = obj->getClass();
if (clasp == &BlockClass) {
char *source = JS_sprintf_append(NULL, "depth %d {", OBJ_BLOCK_DEPTH(cx, obj));
if (obj->isBlock()) {
char *source = JS_sprintf_append(NULL, "depth %d {", obj->asBlock().stackDepth());
if (!source)
return false;
@ -527,15 +525,15 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
return true;
}
if (clasp == &FunctionClass) {
if (obj->isFunction()) {
JSString *str = JS_DecompileFunction(cx, obj->toFunction(), JS_DONT_PRETTY_PRINT);
if (!str)
return false;
return bytes->encode(cx, str);
}
if (clasp == &RegExpClass) {
JSString *source = obj->asRegExp()->toString(cx);
if (obj->isRegExp()) {
JSString *source = obj->asRegExp().toString(cx);
if (!source)
return false;
JS::Anchor<JSString *> anchor(source);
@ -1758,9 +1756,8 @@ GetLocal(SprintStack *ss, jsint i)
JSObject *obj = script->getObject(j);
if (obj->isBlock()) {
jsint depth = OBJ_BLOCK_DEPTH(cx, obj);
jsint count = OBJ_BLOCK_COUNT(cx, obj);
uint32_t depth = obj->asBlock().stackDepth();
uint32_t count = obj->asBlock().slotCount();
if (jsuint(i - depth) < jsuint(count))
return GetLocalInSlot(ss, i, jsint(i - depth), obj);
}
@ -1772,9 +1769,8 @@ GetLocal(SprintStack *ss, jsint i)
JSObject *obj = script->getObject(j);
if (obj->isBlock()) {
jsint depth = OBJ_BLOCK_DEPTH(cx, obj);
jsint count = OBJ_BLOCK_COUNT(cx, obj);
uint32_t depth = obj->asBlock().stackDepth();
uint32_t count = obj->asBlock().slotCount();
if (jsuint(i - depth) < jsuint(count))
return GetLocalInSlot(ss, i, jsint(i - depth), obj);
}
@ -2252,15 +2248,15 @@ DecompileGroupAssignment(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
* back in declaration order.
*/
static bool
GetBlockNames(JSContext *cx, JSObject *blockObj, AtomVector *atoms)
GetBlockNames(JSContext *cx, StaticBlockObject &blockObj, AtomVector *atoms)
{
size_t numAtoms = OBJ_BLOCK_COUNT(cx, blockObj);
size_t numAtoms = blockObj.slotCount();
LOCAL_ASSERT(numAtoms > 0);
if (!atoms->resize(numAtoms))
return false;
uintN i = numAtoms;
for (Shape::Range r = blockObj->lastProperty()->all(); !r.empty(); r.popFront()) {
for (Shape::Range r = blockObj.lastProperty()->all(); !r.empty(); r.popFront()) {
const Shape &shape = r.front();
LOCAL_ASSERT(shape.hasShortID());
--i;
@ -3188,7 +3184,9 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
{
LOAD_OBJECT(0);
AtomVector atoms(cx);
if (!GetBlockNames(cx, obj, &atoms) || !PushBlockNames(cx, ss, atoms))
StaticBlockObject &blockObj = obj->asStaticBlock();
if (!GetBlockNames(cx, blockObj, &atoms) || !PushBlockNames(cx, ss, atoms))
return NULL;
sn = js_GetSrcNote(jp->script, pc);
@ -3246,7 +3244,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
#endif
LOCAL_ASSERT(*pc == JSOP_SETLOCALPOP);
pc += JSOP_SETLOCALPOP_LENGTH;
LOCAL_ASSERT(OBJ_BLOCK_COUNT(cx, obj) >= 1);
LOCAL_ASSERT(blockObj.slotCount() >= 1);
if (!QuoteString(&jp->sprinter, atoms[0], 0))
return NULL;
#if JS_HAS_DESTRUCTURING
@ -3328,18 +3326,19 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_ENTERLET0:
{
LOAD_OBJECT(0);
StaticBlockObject &blockObj = obj->asStaticBlock();
AtomVector atoms(cx);
if (!GetBlockNames(cx, obj, &atoms))
if (!GetBlockNames(cx, blockObj, &atoms))
return NULL;
sn = js_GetSrcNote(jp->script, pc);
LOCAL_ASSERT(SN_TYPE(sn) == SRC_DECL);
ptrdiff_t letData = js_GetSrcNoteOffset(sn, 0);
bool groupAssign = LetDataToGroupAssign(letData);
uintN letDepth = OBJ_BLOCK_DEPTH(cx, obj);
LOCAL_ASSERT(letDepth == (uintN)ss->top - OBJ_BLOCK_COUNT(cx, obj));
LOCAL_ASSERT(atoms.length() == OBJ_BLOCK_COUNT(cx, obj));
uintN letDepth = blockObj.stackDepth();
LOCAL_ASSERT(letDepth == (uintN)ss->top - blockObj.slotCount());
LOCAL_ASSERT(atoms.length() == blockObj.slotCount());
/*
* Build the list of decompiled rhs expressions. Do this before
@ -3449,13 +3448,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_ENTERLET1:
{
LOAD_OBJECT(0);
StaticBlockObject &blockObj = obj->asStaticBlock();
AtomVector atoms(cx);
if (!GetBlockNames(cx, obj, &atoms))
if (!GetBlockNames(cx, blockObj, &atoms))
return NULL;
LOCAL_ASSERT(js_GetSrcNote(jp->script, pc) == NULL);
LOCAL_ASSERT(ss->top - 1 == OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj));
LOCAL_ASSERT(ss->top - 1 == blockObj.stackDepth() + blockObj.slotCount());
jsbytecode *nextpc = pc + JSOP_ENTERLET1_LENGTH;
if (*nextpc == JSOP_GOTO || *nextpc == JSOP_GOTOX) {
LOCAL_ASSERT(SN_TYPE(js_GetSrcNote(jp->script, nextpc)) == SRC_FOR_IN);
@ -4126,13 +4126,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
LOCAL_ASSERT(*(pc + offsetToLet) == JSOP_ENTERLET0);
GET_OBJECT_FROM_BYTECODE(jp->script, pc + offsetToLet, 0, obj);
StaticBlockObject &blockObj = obj->asStaticBlock();
uint32_t blockDepth = OBJ_BLOCK_DEPTH(cx, obj);
uint32_t blockDepth = blockObj.stackDepth();
LOCAL_ASSERT(blockDepth < ss->top);
LOCAL_ASSERT(ss->top <= blockDepth + OBJ_BLOCK_COUNT(cx, obj));
LOCAL_ASSERT(ss->top <= blockDepth + blockObj.slotCount());
AtomVector atoms(cx);
if (!GetBlockNames(cx, obj, &atoms))
if (!GetBlockNames(cx, blockObj, &atoms))
return NULL;
/*
@ -4823,7 +4824,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_REGEXP:
GET_REGEXP_FROM_BYTECODE(jp->script, pc, 0, obj);
str = obj->asRegExp()->toString(cx);
str = obj->asRegExp().toString(cx);
if (!str)
return NULL;
goto sprint_string;

View File

@ -77,7 +77,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, JSObject *po
JSObject *tmp = obj;
for (uintN i = 0; i < scopeIndex; i++)
tmp = tmp->internalScopeChain();
tmp = &tmp->asScope().enclosingScope();
uintN protoIndex = 0;
while (tmp != pobj) {
@ -231,7 +231,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
if (JOF_MODE(cs.format) == JOF_NAME) {
uint8_t scopeIndex = entry->scopeIndex;
while (scopeIndex > 0) {
tmp = pobj->scopeChain();
tmp = pobj->enclosingScope();
if (!tmp || !tmp->isNative())
break;
pobj = tmp;

View File

@ -1539,7 +1539,7 @@ proxy_createFunction(JSContext *cx, uintN argc, Value *vp)
return false;
JSObject *proto, *parent;
parent = vp[0].toObject().getParent();
proto = parent->getGlobal()->getOrCreateFunctionPrototype(cx);
proto = parent->global().getOrCreateFunctionPrototype(cx);
if (!proto)
return false;
parent = proto->getParent();
@ -1653,7 +1653,7 @@ callable_Construct(JSContext *cx, uintN argc, Value *vp)
if (protov.isObject()) {
proto = &protov.toObject();
} else {
proto = callable->getGlobal()->getOrCreateObjectPrototype(cx);
proto = callable->global().getOrCreateObjectPrototype(cx);
if (!proto)
return false;
}

View File

@ -316,6 +316,7 @@ class Handle
T a = RootMethods<T>::initial();
S b = RootMethods<S>::initial();
a = b;
(void)a;
#endif
}
};

View File

@ -1460,7 +1460,7 @@ NewObjectCache::invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject
if (CanBeFinalizedInBackground(kind, clasp))
kind = GetBackgroundAllocKind(kind);
GlobalObject *global = shape->getObjectParent()->getGlobal();
GlobalObject *global = &shape->getObjectParent()->global();
types::TypeObject *type = proto->getNewType(cx);
EntryIndex entry;

View File

@ -535,6 +535,7 @@ struct Shape : public js::gc::Cell
{
friend struct ::JSObject;
friend struct ::JSFunction;
friend class js::StaticBlockObject;
friend class js::PropertyTree;
friend class js::Bindings;
friend struct js::StackShape;

View File

@ -41,6 +41,7 @@
#define jsscopeinlines_h___
#include <new>
#include "jsarray.h"
#include "jsbool.h"
#include "jscntxt.h"
@ -52,12 +53,15 @@
#include "jsgcmark.h"
#include "vm/ArgumentsObject.h"
#include "vm/ScopeObject.h"
#include "vm/StringObject.h"
#include "jscntxtinlines.h"
#include "jsgcinlines.h"
#include "jsobjinlines.h"
#include "vm/ScopeObject-inl.h"
namespace js {
inline
@ -265,7 +269,7 @@ Shape::get(JSContext* cx, JSObject *receiver, JSObject* obj, JSObject *pobj, js:
* Avoid exposing the With object to native getters.
*/
if (obj->isWith())
obj = js_UnwrapWithObject(cx, obj);
obj = &obj->asWith().object();
return js::CallJSPropertyOp(cx, getterOp(), receiver, getUserId(), vp);
}
@ -284,7 +288,7 @@ Shape::set(JSContext* cx, JSObject* obj, bool strict, js::Value* vp) const
/* See the comment in js::Shape::get as to why we check for With. */
if (obj->isWith())
obj = js_UnwrapWithObject(cx, obj);
obj = &obj->asWith().object();
return js::CallJSPropertyOpSetter(cx, setterOp(), obj, getUserId(), strict, vp);
}

View File

@ -653,23 +653,24 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp)
HeapPtr<JSObject> *objp = &script->objects()->vector[i];
uint32_t isBlock;
if (xdr->mode == JSXDR_ENCODE) {
Class *clasp = (*objp)->getClass();
JS_ASSERT(clasp == &FunctionClass ||
clasp == &BlockClass);
isBlock = (clasp == &BlockClass) ? 1 : 0;
JSObject *obj = *objp;
JS_ASSERT(obj->isFunction() || obj->isStaticBlock());
isBlock = obj->isBlock() ? 1 : 0;
}
if (!JS_XDRUint32(xdr, &isBlock))
goto error;
JSObject *tmp = *objp;
if (isBlock == 0) {
JSObject *tmp = *objp;
if (!js_XDRFunctionObject(xdr, &tmp))
goto error;
*objp = tmp;
} else {
JS_ASSERT(isBlock == 1);
if (!js_XDRBlockObject(xdr, &tmp))
StaticBlockObject *tmp = static_cast<StaticBlockObject *>(objp->get());
if (!js_XDRStaticBlockObject(xdr, &tmp))
goto error;
*objp = tmp;
}
*objp = tmp;
}
for (i = 0; i != nupvars; ++i) {
if (!JS_XDRUint32(xdr, reinterpret_cast<uint32_t *>(&script->upvars()->vector[i])))
@ -1261,7 +1262,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
return NULL;
fun->setScript(script);
script->globalObject = fun->getParent() ? fun->getParent()->getGlobal() : NULL;
script->globalObject = fun->getParent() ? &fun->getParent()->global() : NULL;
} else {
/*
* Initialize script->object, if necessary, so that the debugger has a
@ -1278,7 +1279,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
if (script->compileAndGo) {
compileAndGoGlobal = script->globalObject;
if (!compileAndGoGlobal)
compileAndGoGlobal = bce->scopeChain()->getGlobal();
compileAndGoGlobal = &bce->scopeChain()->global();
}
Debugger::onNewScript(cx, script, compileAndGoGlobal);
}

View File

@ -48,7 +48,7 @@
#include "jsscript.h"
#include "jsscope.h"
#include "vm/CallObject.h"
#include "vm/ScopeObject.h"
#include "vm/GlobalObject.h"
#include "vm/RegExpObject.h"

View File

@ -1403,7 +1403,7 @@ class RegExpGuard
init(uintN argc, Value *vp, bool convertVoid = false)
{
if (argc != 0 && ValueIsRegExp(vp[2])) {
if (!rep.reset(vp[2].toObject().asRegExp()))
if (!rep.reset(&vp[2].toObject().asRegExp()))
return false;
} else {
if (convertVoid && (argc == 0 || vp[2].isUndefined())) {
@ -2538,8 +2538,7 @@ js::str_split(JSContext *cx, uintN argc, Value *vp)
bool sepUndefined = (argc == 0 || vp[2].isUndefined());
if (!sepUndefined) {
if (ValueIsRegExp(vp[2])) {
RegExpObject *reobj = vp[2].toObject().asRegExp();
if (!matcher.reset(reobj))
if (!matcher.reset(&vp[2].toObject().asRegExp()))
return false;
} else {
JSString *sep = ToString(cx, vp[2]);
@ -3033,10 +3032,10 @@ js_InitStringClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
JSObject *proto = global->createBlankPrototype(cx, &StringClass);
if (!proto || !proto->asString()->init(cx, cx->runtime->emptyString))
if (!proto || !proto->asString().init(cx, cx->runtime->emptyString))
return NULL;
/* Now create the String function. */

View File

@ -2374,7 +2374,7 @@ js_InitTypedArrayClasses(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
/* Idempotency required: we initialize several things, possibly lazily. */
JSObject *stop;

View File

@ -330,7 +330,7 @@ js_InitWeakMapClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
JSObject *weakMapProto = global->createBlankPrototype(cx, &WeakMapClass);
if (!weakMapProto)

View File

@ -424,10 +424,10 @@ ForceFrame::enter()
JS_ASSERT(context->compartment == target->compartment());
JSCompartment *destination = context->compartment;
JSObject *scopeChain = target->getGlobal();
JS_ASSERT(scopeChain->isNative());
JSObject &scopeChain = target->global();
JS_ASSERT(scopeChain.isNative());
return context->stack.pushDummyFrame(context, destination, *scopeChain, frame);
return context->stack.pushDummyFrame(context, destination, scopeChain, frame);
}
AutoCompartment::AutoCompartment(JSContext *cx, JSObject *target)
@ -450,11 +450,11 @@ AutoCompartment::enter()
{
JS_ASSERT(!entered);
if (origin != destination) {
JSObject *scopeChain = target->getGlobal();
JS_ASSERT(scopeChain->isNative());
JSObject &scopeChain = target->global();
JS_ASSERT(scopeChain.isNative());
frame.construct();
if (!context->stack.pushDummyFrame(context, destination, *scopeChain, &frame.ref()))
if (!context->stack.pushDummyFrame(context, destination, scopeChain, &frame.ref()))
return false;
if (context->isExceptionPending())

View File

@ -4656,7 +4656,7 @@ HasFunctionProperty(JSContext *cx, JSObject *obj, jsid funid, JSBool *found)
* Search in String.prototype to set found whenever
* GetXMLFunction returns existing function.
*/
JSObject *proto = obj->getGlobal()->getOrCreateStringPrototype(cx);
JSObject *proto = obj->global().getOrCreateStringPrototype(cx);
if (!proto)
return false;
@ -7404,7 +7404,7 @@ js_InitNamespaceClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
JSObject *namespaceProto = global->createBlankPrototype(cx, &NamespaceClass);
if (!namespaceProto)
@ -7437,7 +7437,7 @@ js_InitQNameClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
JSObject *qnameProto = global->createBlankPrototype(cx, &QNameClass);
if (!qnameProto)
@ -7469,7 +7469,7 @@ js_InitXMLClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
GlobalObject *global = obj->asGlobal();
GlobalObject *global = &obj->asGlobal();
JSObject *xmlProto = global->createBlankPrototype(cx, &XMLClass);
if (!xmlProto)
@ -7595,9 +7595,8 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
return false;
obj = NULL;
for (tmp = scopeChain; tmp; tmp = tmp->scopeChain()) {
Class *clasp = tmp->getClass();
if (clasp == &BlockClass || clasp == &WithClass)
for (tmp = scopeChain; tmp; tmp = tmp->enclosingScope()) {
if (tmp->isBlock() || tmp->isWith())
continue;
if (!tmp->getSpecial(cx, SpecialId::defaultXMLNamespace(), &v))
return JS_FALSE;
@ -7708,7 +7707,7 @@ js_ValueToXMLString(JSContext *cx, const Value &v)
JSBool
js_GetAnyName(JSContext *cx, jsid *idp)
{
JSObject *global = cx->hasfp() ? cx->fp()->scopeChain().getGlobal() : cx->globalObject;
JSObject *global = cx->hasfp() ? &cx->fp()->scopeChain().global() : cx->globalObject;
Value v = global->getReservedSlot(JSProto_AnyName);
if (v.isUndefined()) {
JSObject *obj = NewObjectWithGivenProto(cx, &AnyNameClass, NULL, global);
@ -7793,7 +7792,7 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *i
return JS_TRUE;
}
}
} while ((obj = obj->scopeChain()) != NULL);
} while ((obj = obj->enclosingScope()) != NULL);
JSAutoByteString printable;
JSString *str = ConvertQNameToString(cx, nameobj);
@ -7829,7 +7828,7 @@ GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
return true;
/* Search in String.prototype to implement 11.2.2.1 Step 3(f). */
JSObject *proto = obj->getGlobal()->getOrCreateStringPrototype(cx);
JSObject *proto = obj->global().getOrCreateStringPrototype(cx);
if (!proto)
return false;

View File

@ -6377,7 +6377,7 @@ mjit::Compiler::jsop_callgname_epilogue()
/* Paths for known object callee. */
if (fval->isConstant()) {
JSObject *obj = &fval->getValue().toObject();
if (obj->getGlobal() == globalObj) {
if (&obj->global() == globalObj) {
frame.push(UndefinedValue());
} else {
prepareStubCall(Uses(1));
@ -6834,7 +6834,7 @@ mjit::Compiler::jsop_regexp()
RegExpStatics *res = globalObj ? globalObj->getRegExpStatics() : NULL;
if (!globalObj ||
obj->getGlobal() != globalObj ||
&obj->global() != globalObj ||
!cx->typeInferenceEnabled() ||
analysis->localsAliasStack() ||
types::TypeSet::HasObjectFlags(cx, globalObj->getType(cx),
@ -6846,7 +6846,7 @@ mjit::Compiler::jsop_regexp()
return true;
}
RegExpObject *reobj = obj->asRegExp();
RegExpObject *reobj = &obj->asRegExp();
DebugOnly<uint32_t> origFlags = reobj->getFlags();
DebugOnly<uint32_t> staticsFlags = res->getFlags();

View File

@ -639,7 +639,7 @@ mjit::Compiler::compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *ar
if (thisTypes->getObjectCount() != 1)
return Compile_InlineAbort;
types::TypeObject *thisType = thisTypes->getTypeObject(0);
if (!thisType || thisType->proto->getGlobal() != globalObj)
if (!thisType || &thisType->proto->global() != globalObj)
return Compile_InlineAbort;
/*
@ -839,7 +839,7 @@ mjit::Compiler::inlineNativeFunction(uint32_t argc, bool callingNew)
* The callee must have the same parent as the script's global, otherwise
* inference may not have accounted for any side effects correctly.
*/
if (!globalObj || globalObj != callee->getGlobal())
if (!globalObj || globalObj != &callee->global())
return Compile_InlineAbort;
Native native = callee->toFunction()->maybeNative();

View File

@ -630,8 +630,8 @@ js_InternalThrow(VMFrame &f)
*/
if (cx->isExceptionPending()) {
JS_ASSERT(JSOp(*pc) == JSOP_ENTERBLOCK);
JSObject *obj = script->getObject(GET_SLOTNO(pc));
Value *vp = cx->regs().sp + OBJ_BLOCK_COUNT(cx, obj);
StaticBlockObject &blockObj = script->getObject(GET_SLOTNO(pc))->asStaticBlock();
Value *vp = cx->regs().sp + blockObj.slotCount();
SetValueRangeToUndefined(cx->regs().sp, vp);
cx->regs().sp = vp;
JS_ASSERT(JSOp(pc[JSOP_ENTERBLOCK_LENGTH]) == JSOP_EXCEPTION);
@ -639,7 +639,7 @@ js_InternalThrow(VMFrame &f)
cx->clearPendingException();
cx->regs().sp++;
cx->regs().pc = pc + JSOP_ENTERBLOCK_LENGTH + JSOP_EXCEPTION_LENGTH;
cx->regs().fp()->setBlockChain(obj);
cx->regs().fp()->setBlockChain(&blockObj);
}
*f.oldregs = f.regs;

View File

@ -86,13 +86,13 @@ PatchGetFallback(VMFrame &f, ic::GetGlobalNameIC *ic)
void JS_FASTCALL
ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
{
JSObject *obj = f.fp()->scopeChain().getGlobal();
JSObject &obj = f.fp()->scopeChain().global();
JSAtom *atom = f.script()->getAtom(GET_INDEX(f.pc()));
jsid id = ATOM_TO_JSID(atom);
RecompilationMonitor monitor(f.cx);
const Shape *shape = obj->nativeLookup(f.cx, id);
const Shape *shape = obj.nativeLookup(f.cx, id);
if (monitor.recompiled()) {
stubs::GetGlobalName(f);
@ -112,10 +112,10 @@ ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
/* Patch shape guard. */
Repatcher repatcher(f.jit());
repatcher.repatch(ic->fastPathStart.dataLabelPtrAtOffset(ic->shapeOffset), obj->lastProperty());
repatcher.repatch(ic->fastPathStart.dataLabelPtrAtOffset(ic->shapeOffset), obj.lastProperty());
/* Patch loads. */
uint32_t index = obj->dynamicSlotIndex(slot);
uint32_t index = obj.dynamicSlotIndex(slot);
JSC::CodeLocationLabel label = ic->fastPathStart.labelAtOffset(ic->loadStoreOffset);
repatcher.patchAddressOffsetForValueLoad(label, index * sizeof(Value));
@ -208,16 +208,16 @@ UpdateSetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, const Sh
void JS_FASTCALL
ic::SetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic)
{
JSObject *obj = f.fp()->scopeChain().getGlobal();
JSObject &obj = f.fp()->scopeChain().global();
JSScript *script = f.script();
JSAtom *atom = script->getAtom(GET_INDEX(f.pc()));
RecompilationMonitor monitor(f.cx);
const Shape *shape = obj->nativeLookup(f.cx, ATOM_TO_JSID(atom));
const Shape *shape = obj.nativeLookup(f.cx, ATOM_TO_JSID(atom));
if (!monitor.recompiled()) {
LookupStatus status = UpdateSetGlobalName(f, ic, obj, shape);
LookupStatus status = UpdateSetGlobalName(f, ic, &obj, shape);
if (status == Lookup_Error)
THROW();
}

View File

@ -54,7 +54,7 @@
#include "jsinterpinlines.h"
#include "jsautooplen.h"
#include "vm/CallObject-inl.h"
#include "vm/ScopeObject-inl.h"
#if defined JS_POLYIC
@ -1443,10 +1443,10 @@ class ScopeNameCompiler : public PICStubCompiler
return error();
/* Load the next link in the scope chain. */
Address parent(pic.objReg, JSObject::offsetOfInternalScopeChain());
Address parent(pic.objReg, ScopeObject::offsetOfEnclosingScope());
masm.loadPayload(parent, pic.objReg);
tobj = tobj->internalScopeChain();
tobj = &tobj->asScope().enclosingScope();
}
if (tobj != getprop.holder)
@ -1501,7 +1501,7 @@ class ScopeNameCompiler : public PICStubCompiler
masm.loadPtr(Address(JSFrameReg, StackFrame::offsetOfScopeChain()), pic.objReg);
JS_ASSERT(obj == getprop.holder);
JS_ASSERT(getprop.holder == scopeChain->getGlobal());
JS_ASSERT(getprop.holder == &scopeChain->global());
LookupStatus status = walkScopeChain(masm, fails);
if (status != Lookup_Cacheable)
@ -1585,7 +1585,7 @@ class ScopeNameCompiler : public PICStubCompiler
masm.loadPtr(Address(JSFrameReg, StackFrame::offsetOfScopeChain()), pic.objReg);
JS_ASSERT(obj == getprop.holder);
JS_ASSERT(getprop.holder != scopeChain->getGlobal());
JS_ASSERT(getprop.holder != &scopeChain->global());
CallObjPropKind kind;
const Shape *shape = getprop.shape;
@ -1763,7 +1763,7 @@ class ScopeNameCompiler : public PICStubCompiler
const Shape *shape = getprop.shape;
JSObject *normalized = obj;
if (obj->isWith() && !shape->hasDefaultGetter())
normalized = js_UnwrapWithObject(cx, obj);
normalized = &obj->asWith().object();
NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, return false);
if (thisvp)
return ComputeImplicitThis(cx, normalized, *vp, thisvp);
@ -1825,7 +1825,7 @@ class BindNameCompiler : public PICStubCompiler
/* Walk up the scope chain. */
JSObject *tobj = scopeChain;
Address parent(pic.objReg, JSObject::offsetOfInternalScopeChain());
Address parent(pic.objReg, ScopeObject::offsetOfEnclosingScope());
while (tobj && tobj != obj) {
if (!IsCacheableNonGlobalScope(tobj))
return disable("non-cacheable obj in scope chain");
@ -1835,7 +1835,7 @@ class BindNameCompiler : public PICStubCompiler
ImmPtr(tobj->lastProperty()));
if (!fails.append(shapeTest))
return error();
tobj = tobj->internalScopeChain();
tobj = &tobj->asScope().enclosingScope();
}
if (tobj != obj)
return disable("indirect hit");
@ -1932,7 +1932,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
} else if (!f.regs.sp[-1].isPrimitive()) {
JSObject *obj = &f.regs.sp[-1].toObject();
if (obj->isArray() ||
(obj->isArguments() && !obj->asArguments()->hasOverriddenLength()) ||
(obj->isArguments() && !obj->asArguments().hasOverriddenLength()) ||
obj->isString()) {
GetPropCompiler cc(f, script, obj, *pic, NULL, DisabledGetPropIC);
if (obj->isArray()) {
@ -1944,7 +1944,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
LookupStatus status = cc.generateArgsLengthStub();
if (status == Lookup_Error)
THROW();
f.regs.sp[-1].setInt32(int32_t(obj->asArguments()->initialLength()));
f.regs.sp[-1].setInt32(int32_t(obj->asArguments().initialLength()));
} else if (obj->isString()) {
LookupStatus status = cc.generateStringObjLengthStub();
if (status == Lookup_Error)
@ -2069,14 +2069,14 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic)
if (lval.isObject()) {
objv = lval;
} else {
GlobalObject *global = f.fp()->scopeChain().getGlobal();
GlobalObject &global = f.fp()->scopeChain().global();
JSObject *pobj;
if (lval.isString()) {
pobj = global->getOrCreateStringPrototype(cx);
pobj = global.getOrCreateStringPrototype(cx);
} else if (lval.isNumber()) {
pobj = global->getOrCreateNumberPrototype(cx);
pobj = global.getOrCreateNumberPrototype(cx);
} else if (lval.isBoolean()) {
pobj = global->getOrCreateBooleanPrototype(cx);
pobj = global.getOrCreateBooleanPrototype(cx);
} else {
JS_ASSERT(lval.isNull() || lval.isUndefined());
js_ReportIsNullOrUndefined(cx, -1, lval, NULL);

View File

@ -118,7 +118,7 @@ stubs::BindNameNoCache(VMFrame &f, JSAtom *atom)
JSObject * JS_FASTCALL
stubs::BindGlobalName(VMFrame &f)
{
return f.fp()->scopeChain().getGlobal();
return &f.fp()->scopeChain().global();
}
template<JSBool strict>
@ -317,7 +317,7 @@ NameOp(VMFrame &f, JSObject *obj, bool callname)
Shape *shape = (Shape *)prop;
JSObject *normalized = obj;
if (normalized->isWith() && !shape->hasDefaultGetter())
normalized = js_UnwrapWithObject(cx, normalized);
normalized = &normalized->asWith().object();
NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL);
}
@ -347,7 +347,7 @@ stubs::Name(VMFrame &f)
void JS_FASTCALL
stubs::GetGlobalName(VMFrame &f)
{
JSObject *globalObj = f.fp()->scopeChain().getGlobal();
JSObject *globalObj = &f.fp()->scopeChain().global();
if (!NameOp(f, globalObj, false))
THROW();
}
@ -395,7 +395,7 @@ stubs::GetElem(VMFrame &f)
return;
}
} else if (obj->isArguments()) {
if (obj->asArguments()->getElement(index, &rval))
if (obj->asArguments().getElement(index, &rval))
return;
}
@ -556,7 +556,7 @@ stubs::CallName(VMFrame &f)
void JS_FASTCALL
stubs::PushImplicitThisForGlobal(VMFrame &f)
{
return PushImplicitThis(f, f.fp()->scopeChain().getGlobal(), f.regs.sp[-1]);
return PushImplicitThis(f, &f.fp()->scopeChain().global(), f.regs.sp[-1]);
}
void JS_FASTCALL
@ -691,7 +691,7 @@ stubs::DefFun(VMFrame &f, JSFunction *fun)
obj = CloneFunctionObjectIfNotSingleton(cx, fun, obj2);
if (!obj)
THROW();
JS_ASSERT_IF(f.script()->compileAndGo, obj->getGlobal() == fun->getGlobal());
JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
}
/*
@ -1341,7 +1341,7 @@ stubs::DefLocalFun(VMFrame &f, JSFunction *fun)
if (!obj)
THROWV(NULL);
JS_ASSERT_IF(f.script()->compileAndGo, obj->getGlobal() == fun->getGlobal());
JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
return obj;
}
@ -1362,7 +1362,7 @@ stubs::RegExp(VMFrame &f, JSObject *regex)
* Push a regexp object cloned from the regexp literal object mapped by the
* bytecode at pc.
*/
JSObject *proto = f.fp()->scopeChain().getGlobal()->getOrCreateRegExpPrototype(f.cx);
JSObject *proto = f.fp()->scopeChain().global().getOrCreateRegExpPrototype(f.cx);
if (!proto)
THROW();
JS_ASSERT(proto);
@ -1451,7 +1451,7 @@ stubs::Lambda(VMFrame &f, JSFunction *fun)
if (!obj)
THROWV(NULL);
JS_ASSERT_IF(f.script()->compileAndGo, obj->getGlobal() == fun->getGlobal());
JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
return obj;
}
@ -1536,14 +1536,14 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom)
if (lval.isObject()) {
objv = lval;
} else {
GlobalObject *global = f.fp()->scopeChain().getGlobal();
GlobalObject &global = f.fp()->scopeChain().global();
JSObject *pobj;
if (lval.isString()) {
pobj = global->getOrCreateStringPrototype(cx);
pobj = global.getOrCreateStringPrototype(cx);
} else if (lval.isNumber()) {
pobj = global->getOrCreateNumberPrototype(cx);
pobj = global.getOrCreateNumberPrototype(cx);
} else if (lval.isBoolean()) {
pobj = global->getOrCreateBooleanPrototype(cx);
pobj = global.getOrCreateBooleanPrototype(cx);
} else {
JS_ASSERT(lval.isNull() || lval.isUndefined());
js_ReportIsNullOrUndefined(cx, -1, lval, NULL);
@ -1819,13 +1819,13 @@ stubs::EnterBlock(VMFrame &f, JSObject *obj)
{
FrameRegs &regs = f.regs;
StackFrame *fp = f.fp();
StaticBlockObject &blockObj = obj->asStaticBlock();
JS_ASSERT(!f.regs.inlined());
JS_ASSERT(obj->isStaticBlock());
if (*regs.pc == JSOP_ENTERBLOCK) {
JS_ASSERT(fp->base() + OBJ_BLOCK_DEPTH(cx, obj) == regs.sp);
Value *vp = regs.sp + OBJ_BLOCK_COUNT(cx, obj);
JS_ASSERT(fp->base() + blockObj.stackDepth() == regs.sp);
Value *vp = regs.sp + blockObj.slotCount();
JS_ASSERT(regs.sp < vp);
JS_ASSERT(vp <= fp->slots() + fp->script()->nslots);
SetValueRangeToUndefined(regs.sp, vp);
@ -1834,7 +1834,7 @@ stubs::EnterBlock(VMFrame &f, JSObject *obj)
#ifdef DEBUG
JSContext *cx = f.cx;
JS_ASSERT(fp->maybeBlockChain() == obj->staticBlockScopeChain());
JS_ASSERT(fp->maybeBlockChain() == blockObj.enclosingBlock());
/*
* The young end of fp->scopeChain() may omit blocks if we haven't closed
@ -1845,18 +1845,17 @@ stubs::EnterBlock(VMFrame &f, JSObject *obj)
*/
JSObject *obj2 = &fp->scopeChain();
while (obj2->isWith())
obj2 = obj2->internalScopeChain();
obj2 = &obj2->asWith().enclosingScope();
if (obj2->isBlock() &&
obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, fp)) {
JSObject *youngestProto = obj2->getProto();
JS_ASSERT(youngestProto->isStaticBlock());
JSObject *parent = obj;
while ((parent = parent->scopeChain()) != youngestProto)
JSObject &youngestProto = obj2->asClonedBlock().staticBlock();
StaticBlockObject *parent = &blockObj;
while ((parent = parent->enclosingBlock()) != &youngestProto)
JS_ASSERT(parent);
}
#endif
fp->setBlockChain(obj);
fp->setBlockChain(&blockObj);
}
void JS_FASTCALL
@ -1865,26 +1864,19 @@ stubs::LeaveBlock(VMFrame &f)
JSContext *cx = f.cx;
StackFrame *fp = f.fp();
#ifdef DEBUG
JS_ASSERT(fp->blockChain().isBlock());
uintN blockDepth = OBJ_BLOCK_DEPTH(cx, &fp->blockChain());
StaticBlockObject &blockObj = fp->blockChain();
JS_ASSERT(blockObj.stackDepth() <= StackDepth(fp->script()));
JS_ASSERT(blockDepth <= StackDepth(fp->script()));
#endif
/*
* If we're about to leave the dynamic scope of a block that has been
* cloned onto fp->scopeChain(), clear its private data, move its locals from
* the stack into the clone, and pop it off the chain.
*/
JSObject &obj = fp->scopeChain();
JSObject &blockChain = fp->blockChain();
if (obj.getProto() == &blockChain) {
JS_ASSERT(obj.isBlock());
if (!js_PutBlockObject(cx, JS_TRUE))
THROW();
}
if (obj.getProto() == &blockObj && !obj.asClonedBlock().put(cx, JS_TRUE))
THROW();
fp->setBlockChain(blockChain.staticBlockScopeChain());
fp->setBlockChain(blockObj.enclosingBlock());
}
void * JS_FASTCALL

View File

@ -3740,7 +3740,7 @@ Wrap(JSContext *cx, uintN argc, jsval *vp)
}
JSObject *obj = JSVAL_TO_OBJECT(v);
JSObject *wrapped = Wrapper::New(cx, obj, obj->getProto(), obj->getGlobal(),
JSObject *wrapped = Wrapper::New(cx, obj, obj->getProto(), &obj->global(),
&Wrapper::singleton);
if (!wrapped)
return false;

View File

@ -141,7 +141,7 @@ struct ArgumentsData
* remove this oddity, but preserving it allows us to work with arguments
* objects of either kind more abstractly, so we keep it for now.
*/
class ArgumentsObject : public ::JSObject
class ArgumentsObject : public JSObject
{
static const uint32_t INITIAL_LENGTH_SLOT = 0;
static const uint32_t DATA_SLOT = 1;
@ -243,25 +243,25 @@ class StrictArgumentsObject : public ArgumentsObject
} // namespace js
js::NormalArgumentsObject *
js::NormalArgumentsObject &
JSObject::asNormalArguments()
{
JS_ASSERT(isNormalArguments());
return reinterpret_cast<js::NormalArgumentsObject *>(this);
return *reinterpret_cast<js::NormalArgumentsObject *>(this);
}
js::StrictArgumentsObject *
js::StrictArgumentsObject &
JSObject::asStrictArguments()
{
JS_ASSERT(isStrictArguments());
return reinterpret_cast<js::StrictArgumentsObject *>(this);
return *reinterpret_cast<js::StrictArgumentsObject *>(this);
}
js::ArgumentsObject *
js::ArgumentsObject &
JSObject::asArguments()
{
JS_ASSERT(isArguments());
return reinterpret_cast<js::ArgumentsObject *>(this);
return *reinterpret_cast<js::ArgumentsObject *>(this);
}
#endif /* ArgumentsObject_h___ */

View File

@ -45,11 +45,11 @@
#include "vm/BooleanObject.h"
inline js::BooleanObject *
inline js::BooleanObject &
JSObject::asBoolean()
{
JS_ASSERT(isBoolean());
return static_cast<js::BooleanObject *>(const_cast<JSObject *>(this));
return *static_cast<js::BooleanObject *>(this);
}
namespace js {
@ -60,9 +60,9 @@ BooleanObject::create(JSContext *cx, bool b)
JSObject *obj = NewBuiltinClassInstance(cx, &BooleanClass);
if (!obj)
return NULL;
BooleanObject *boolobj = obj->asBoolean();
boolobj->setPrimitiveValue(b);
return boolobj;
BooleanObject &boolobj = obj->asBoolean();
boolobj.setPrimitiveValue(b);
return &boolobj;
}
inline BooleanObject *
@ -72,9 +72,9 @@ BooleanObject::createWithProto(JSContext *cx, bool b, JSObject &proto)
gc::GetGCObjectKind(RESERVED_SLOTS));
if (!obj)
return NULL;
BooleanObject *boolobj = obj->asBoolean();
boolobj->setPrimitiveValue(b);
return boolobj;
BooleanObject &boolobj = obj->asBoolean();
boolobj.setPrimitiveValue(b);
return &boolobj;
}
} // namespace js

View File

@ -47,7 +47,7 @@
namespace js {
class BooleanObject : public ::JSObject
class BooleanObject : public JSObject
{
/* Stores this Boolean object's [[PrimitiveValue]]. */
static const uintN PRIMITIVE_VALUE_SLOT = 0;

View File

@ -1,191 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey call object code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul Biggar <pbiggar@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef CallObject_inl_h___
#define CallObject_inl_h___
#include "CallObject.h"
namespace js {
inline bool
CallObject::isForEval() const
{
JS_ASSERT(getFixedSlot(CALLEE_SLOT).isObjectOrNull());
JS_ASSERT_IF(getFixedSlot(CALLEE_SLOT).isObject(),
getFixedSlot(CALLEE_SLOT).toObject().isFunction());
return getFixedSlot(CALLEE_SLOT).isNull();
}
inline js::StackFrame *
CallObject::maybeStackFrame() const
{
return reinterpret_cast<js::StackFrame *>(getPrivate());
}
inline void
CallObject::setStackFrame(StackFrame *frame)
{
return setPrivate(frame);
}
inline void
CallObject::setCallee(JSObject *callee)
{
JS_ASSERT_IF(callee, callee->isFunction());
setFixedSlot(CALLEE_SLOT, js::ObjectOrNullValue(callee));
}
inline void
CallObject::initCallee(JSObject *callee)
{
JS_ASSERT_IF(callee, callee->isFunction());
initFixedSlot(CALLEE_SLOT, js::ObjectOrNullValue(callee));
}
inline JSObject *
CallObject::getCallee() const
{
return getFixedSlot(CALLEE_SLOT).toObjectOrNull();
}
inline JSFunction *
CallObject::getCalleeFunction() const
{
return getFixedSlot(CALLEE_SLOT).toObject().toFunction();
}
inline const js::Value &
CallObject::getArguments() const
{
JS_ASSERT(!isForEval());
return getFixedSlot(ARGUMENTS_SLOT);
}
inline void
CallObject::setArguments(const js::Value &v)
{
JS_ASSERT(!isForEval());
setFixedSlot(ARGUMENTS_SLOT, v);
}
inline void
CallObject::initArguments(const js::Value &v)
{
JS_ASSERT(!isForEval());
initFixedSlot(ARGUMENTS_SLOT, v);
}
inline const js::Value &
CallObject::arg(uintN i) const
{
JS_ASSERT(i < getCalleeFunction()->nargs);
return getSlot(RESERVED_SLOTS + i);
}
inline void
CallObject::setArg(uintN i, const js::Value &v)
{
JS_ASSERT(i < getCalleeFunction()->nargs);
setSlot(RESERVED_SLOTS + i, v);
}
inline void
CallObject::initArgUnchecked(uintN i, const js::Value &v)
{
JS_ASSERT(i < getCalleeFunction()->nargs);
initSlotUnchecked(RESERVED_SLOTS + i, v);
}
inline const js::Value &
CallObject::var(uintN i) const
{
JSFunction *fun = getCalleeFunction();
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
JS_ASSERT(i < fun->script()->bindings.countVars());
return getSlot(RESERVED_SLOTS + fun->nargs + i);
}
inline void
CallObject::setVar(uintN i, const js::Value &v)
{
JSFunction *fun = getCalleeFunction();
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
JS_ASSERT(i < fun->script()->bindings.countVars());
setSlot(RESERVED_SLOTS + fun->nargs + i, v);
}
inline void
CallObject::initVarUnchecked(uintN i, const js::Value &v)
{
JSFunction *fun = getCalleeFunction();
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
JS_ASSERT(i < fun->script()->bindings.countVars());
initSlotUnchecked(RESERVED_SLOTS + fun->nargs + i, v);
}
inline void
CallObject::copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots)
{
JS_ASSERT(slotInRange(RESERVED_SLOTS + nargs + nvars, SENTINEL_ALLOWED));
copySlotRange(RESERVED_SLOTS, argv, nargs);
copySlotRange(RESERVED_SLOTS + nargs, slots, nvars);
}
inline js::HeapValueArray
CallObject::argArray()
{
js::DebugOnly<JSFunction*> fun = getCalleeFunction();
JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS, fun->nargs));
return HeapValueArray(getSlotAddress(RESERVED_SLOTS));
}
inline js::HeapValueArray
CallObject::varArray()
{
JSFunction *fun = getCalleeFunction();
JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS + fun->nargs,
fun->script()->bindings.countVars()));
return HeapValueArray(getSlotAddress(RESERVED_SLOTS + fun->nargs));
}
}
#endif /* CallObject_inl_h___ */

View File

@ -1,117 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey call object code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul Biggar <pbiggar@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "jsobjinlines.h"
#include "CallObject.h"
#include "CallObject-inl.h"
namespace js {
/*
* Construct a call object for the given bindings. If this is a call object
* for a function invocation, callee should be the function being called.
* Otherwise it must be a call object for eval of strict mode code, and callee
* must be null.
*/
CallObject *
CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObject *callee)
{
Bindings &bindings = script->bindings;
gc::AllocKind kind = gc::GetGCObjectKind(bindings.lastShape()->numFixedSlots() + 1);
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
HeapValue *slots;
if (!PreallocateObjectDynamicSlots(cx, bindings.lastShape(), &slots))
return NULL;
RootedVarShape shape(cx);
shape = bindings.lastShape();
JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
if (!obj)
return NULL;
/*
* Update the parent for bindings associated with non-compileAndGo scripts,
* whose call objects do not have a consistent global variable and need
* to be updated dynamically.
*/
JSObject *global = scopeChain.getGlobal();
if (global != obj->getParent()) {
JS_ASSERT(obj->getParent() == NULL);
if (!obj->setParent(cx, global))
return NULL;
}
#ifdef DEBUG
for (Shape::Range r = obj->lastProperty(); !r.empty(); r.popFront()) {
const Shape &s = r.front();
if (s.hasSlot()) {
JS_ASSERT(s.slot() + 1 == obj->slotSpan());
break;
}
}
#endif
JS_ASSERT(obj->isCall());
JS_ASSERT(!obj->inDictionaryMode());
if (!obj->setInternalScopeChain(cx, &scopeChain))
return NULL;
/*
* If |bindings| is for a function that has extensible parents, that means
* its Call should have its own shape; see js::BaseShape::extensibleParents.
*/
if (obj->lastProperty()->extensibleParents() && !obj->generateOwnShape(cx))
return NULL;
CallObject &callobj = obj->asCall();
callobj.initCallee(callee);
return &callobj;
}
}

View File

@ -1,127 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey call object code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul Biggar <pbiggar@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef CallObject_h___
#define CallObject_h___
namespace js {
class CallObject : public ::JSObject
{
/*
* Reserved slot structure for Call objects:
*
* SCOPE_CHAIN_SLOT - The enclosing scope. This must come first, for
* JSObject::scopeParent.
* CALLEE_SLOT - Callee function for the stack frame, or null if
* the stack frame is for strict mode eval code.
* ARGUMENTS_SLOT - Arguments object for non-strict mode eval stack
* frames (not valid for strict mode eval frames).
* private - The stack frame corresponding to the Call object
* until js_PutCallObject or its on-trace analog
* is called, null thereafter.
*
* DeclEnv objects use SCOPE_CHAIN_SLOT and private in the same fashion.
*/
static const uint32_t CALLEE_SLOT = 1;
static const uint32_t ARGUMENTS_SLOT = 2;
public:
/* Create a CallObject for the given callee function. */
static CallObject *
create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObject *callee);
static const uint32_t RESERVED_SLOTS = 3;
static const uint32_t DECL_ENV_RESERVED_SLOTS = 1;
static const gc::AllocKind DECL_ENV_FINALIZE_KIND = gc::FINALIZE_OBJECT2;
/* True if this is for a strict mode eval frame or for a function call. */
inline bool isForEval() const;
/* The stack frame for this CallObject, if the frame is still active. */
inline js::StackFrame *maybeStackFrame() const;
inline void setStackFrame(js::StackFrame *frame);
/*
* The callee function if this CallObject was created for a function
* invocation, or null if it was created for a strict mode eval frame.
*/
inline JSObject *getCallee() const;
inline JSFunction *getCalleeFunction() const;
inline void setCallee(JSObject *callee);
inline void initCallee(JSObject *callee);
/* Returns the callee's arguments object. */
inline const js::Value &getArguments() const;
inline void setArguments(const js::Value &v);
inline void initArguments(const js::Value &v);
/* Returns the formal argument at the given index. */
inline const js::Value &arg(uintN i) const;
inline void setArg(uintN i, const js::Value &v);
inline void initArgUnchecked(uintN i, const js::Value &v);
/* Returns the variable at the given index. */
inline const js::Value &var(uintN i) const;
inline void setVar(uintN i, const js::Value &v);
inline void initVarUnchecked(uintN i, const js::Value &v);
/*
* Get the actual arrays of arguments and variables. Only call if type
* inference is enabled, where we ensure that call object variables are in
* contiguous slots (see NewCallObject).
*/
inline js::HeapValueArray argArray();
inline js::HeapValueArray varArray();
inline void copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots);
};
}
js::CallObject &
JSObject::asCall()
{
JS_ASSERT(isCall());
return *reinterpret_cast<js::CallObject *>(this);
}
#endif /* CallObject_h___ */

View File

@ -171,7 +171,7 @@ ScriptGlobal(JSContext *cx, JSScript *script, GlobalObject *scriptGlobal)
for (AllFramesIter i(cx->stack.space()); ; ++i) {
JS_ASSERT(!i.done());
if (i.fp()->maybeScript() == script)
return i.fp()->scopeChain().getGlobal();
return &i.fp()->scopeChain().global();
}
JS_NOT_REACHED("ScriptGlobal: live non-held script not on stack");
}
@ -431,7 +431,7 @@ Debugger::slowPathOnEnterFrame(JSContext *cx, Value *vp)
{
/* Build the list of recipients. */
AutoValueVector triggered(cx);
GlobalObject *global = cx->fp()->scopeChain().getGlobal();
GlobalObject *global = &cx->fp()->scopeChain().global();
if (GlobalObject::DebuggerVector *debuggers = global->getDebuggers()) {
for (Debugger **p = debuggers->begin(); p != debuggers->end(); p++) {
Debugger *dbg = *p;
@ -458,7 +458,7 @@ void
Debugger::slowPathOnLeaveFrame(JSContext *cx)
{
StackFrame *fp = cx->fp();
GlobalObject *global = fp->scopeChain().getGlobal();
GlobalObject *global = &fp->scopeChain().global();
/*
* FIXME This notifies only current debuggers, so it relies on a hack in
@ -811,7 +811,7 @@ Debugger::dispatchHook(JSContext *cx, Value *vp, Hook which)
* different compartments--every compartment *except* this one.
*/
AutoValueVector triggered(cx);
GlobalObject *global = cx->fp()->scopeChain().getGlobal();
GlobalObject *global = &cx->fp()->scopeChain().global();
if (GlobalObject::DebuggerVector *debuggers = global->getDebuggers()) {
for (Debugger **p = debuggers->begin(); p != debuggers->end(); p++) {
Debugger *dbg = *p;
@ -899,7 +899,7 @@ Debugger::onTrap(JSContext *cx, Value *vp)
{
StackFrame *fp = cx->fp();
JSScript *script = fp->script();
GlobalObject *scriptGlobal = fp->scopeChain().getGlobal();
GlobalObject *scriptGlobal = &fp->scopeChain().global();
jsbytecode *pc = cx->regs().pc;
BreakpointSite *site = script->getBreakpointSite(pc);
JSOp op = JSOp(*pc);
@ -975,7 +975,7 @@ Debugger::onSingleStep(JSContext *cx, Value *vp)
* onStep handlers.
*/
AutoObjectVector frames(cx);
GlobalObject *global = fp->scopeChain().getGlobal();
GlobalObject *global = &fp->scopeChain().global();
if (GlobalObject::DebuggerVector *debuggers = global->getDebuggers()) {
for (Debugger **d = debuggers->begin(); d != debuggers->end(); d++) {
Debugger *dbg = *d;
@ -1536,7 +1536,7 @@ Debugger::addDebuggee(JSContext *cx, uintN argc, Value *vp)
JSObject *referent = dbg->unwrapDebuggeeArgument(cx, args[0]);
if (!referent)
return false;
GlobalObject *global = referent->getGlobal();
GlobalObject *global = &referent->global();
if (!dbg->addDebuggeeGlobal(cx, global))
return false;
@ -1555,7 +1555,7 @@ Debugger::removeDebuggee(JSContext *cx, uintN argc, Value *vp)
JSObject *referent = dbg->unwrapDebuggeeArgument(cx, args[0]);
if (!referent)
return false;
GlobalObject *global = referent->getGlobal();
GlobalObject *global = &referent->global();
if (dbg->debuggees.has(global))
dbg->removeDebuggeeGlobal(cx, global, NULL, NULL);
args.rval().setUndefined();
@ -1570,7 +1570,7 @@ Debugger::hasDebuggee(JSContext *cx, uintN argc, Value *vp)
JSObject *referent = dbg->unwrapDebuggeeArgument(cx, args[0]);
if (!referent)
return false;
args.rval().setBoolean(!!dbg->debuggees.lookup(referent->getGlobal()));
args.rval().setBoolean(!!dbg->debuggees.lookup(&referent->global()));
return true;
}
@ -1665,7 +1665,7 @@ Debugger::construct(JSContext *cx, uintN argc, Value *vp)
/* Add the initial debuggees, if any. */
for (uintN i = 0; i < argc; i++) {
GlobalObject *debuggee = GetProxyPrivate(&args[i].toObject()).toObject().getGlobal();
GlobalObject *debuggee = &GetProxyPrivate(&args[i].toObject()).toObject().global();
if (!dbg->addDebuggeeGlobal(cx, debuggee))
return false;
}
@ -1773,7 +1773,7 @@ Debugger::removeDebuggeeGlobal(JSContext *cx, GlobalObject *global,
*/
for (FrameMap::Enum e(frames); !e.empty(); e.popFront()) {
StackFrame *fp = e.front().key;
if (fp->scopeChain().getGlobal() == global) {
if (&fp->scopeChain().global() == global) {
e.front().value->setPrivate(NULL);
e.removeFront();
}
@ -2637,7 +2637,7 @@ DebuggerFrame_getArguments(JSContext *cx, uintN argc, Value *vp)
if (fp->hasArgs()) {
/* Create an arguments object. */
RootedVar<GlobalObject*> global(cx);
global = args.callee().getGlobal();
global = &args.callee().global();
JSObject *proto;
if (!js_GetClassPrototype(cx, global, JSProto_Array, &proto))
return false;
@ -3683,7 +3683,7 @@ DebuggerEnv_getParent(JSContext *cx, uintN argc, Value *vp)
THIS_DEBUGENV_OWNER(cx, argc, vp, "get parent", args, envobj, env, dbg);
/* Don't bother switching compartments just to get env's parent. */
Env *parent = env->scopeChain();
Env *parent = env->enclosingScope();
return dbg->wrapEnvironment(cx, parent, &args.rval());
}
@ -3760,7 +3760,7 @@ DebuggerEnv_find(JSContext *cx, uintN argc, Value *vp)
ErrorCopier ec(ac, dbg->toJSObject());
JSProperty *prop = NULL;
JSObject *pobj;
for (; env && !prop; env = env->scopeChain()) {
for (; env && !prop; env = env->enclosingScope()) {
if (!env->lookupGeneric(cx, id, &pobj, &prop))
return false;
if (prop)

View File

@ -483,7 +483,7 @@ Debugger::observesGlobal(GlobalObject *global) const
bool
Debugger::observesFrame(StackFrame *fp) const
{
return observesGlobal(fp->scopeChain().getGlobal());
return observesGlobal(&fp->scopeChain().global());
}
JSTrapStatus

View File

@ -60,7 +60,7 @@ js_InitObjectClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
return obj->asGlobal()->getOrCreateObjectPrototype(cx);
return obj->asGlobal().getOrCreateObjectPrototype(cx);
}
JSObject *
@ -68,7 +68,7 @@ js_InitFunctionClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
return obj->asGlobal()->getOrCreateFunctionPrototype(cx);
return obj->asGlobal().getOrCreateFunctionPrototype(cx);
}
static JSBool
@ -272,7 +272,7 @@ GlobalObject::create(JSContext *cx, Class *clasp)
JSObject *obj_ = NewObjectWithGivenProto(cx, clasp, NULL, NULL);
if (!obj_)
return NULL;
obj = obj_->asGlobal();
obj = &obj_->asGlobal();
if (!obj->setSingletonType(cx) || !obj->setVarObj(cx))
return NULL;

View File

@ -91,7 +91,7 @@ class Debugger;
* even deletable) Object, Array, &c. properties (although a slot won't be used
* again if its property is deleted and readded).
*/
class GlobalObject : public ::JSObject {
class GlobalObject : public JSObject {
GlobalObject(const GlobalObject &other) MOZ_DELETE;
void operator=(const GlobalObject &other) MOZ_DELETE;
@ -372,11 +372,11 @@ JSObject::isGlobal() const
return !!(js::GetObjectClass(this)->flags & JSCLASS_IS_GLOBAL);
}
js::GlobalObject *
js::GlobalObject &
JSObject::asGlobal()
{
JS_ASSERT(isGlobal());
return static_cast<js::GlobalObject *>(this);
return *static_cast<js::GlobalObject *>(this);
}
#endif /* GlobalObject_h___ */

View File

@ -43,11 +43,11 @@
#include "NumberObject.h"
inline js::NumberObject *
inline js::NumberObject &
JSObject::asNumber()
{
JS_ASSERT(isNumber());
return static_cast<js::NumberObject *>(const_cast<JSObject *>(this));
return *static_cast<js::NumberObject *>(this);
}
namespace js {
@ -58,9 +58,9 @@ NumberObject::create(JSContext *cx, jsdouble d)
JSObject *obj = NewBuiltinClassInstance(cx, &NumberClass);
if (!obj)
return NULL;
NumberObject *numobj = obj->asNumber();
numobj->setPrimitiveValue(d);
return numobj;
NumberObject &numobj = obj->asNumber();
numobj.setPrimitiveValue(d);
return &numobj;
}
inline NumberObject *
@ -70,9 +70,9 @@ NumberObject::createWithProto(JSContext *cx, jsdouble d, JSObject &proto)
gc::GetGCObjectKind(RESERVED_SLOTS));
if (!obj)
return NULL;
NumberObject *numobj = obj->asNumber();
numobj->setPrimitiveValue(d);
return numobj;
NumberObject &numobj = obj->asNumber();
numobj.setPrimitiveValue(d);
return &numobj;
}
} // namespace js

View File

@ -47,7 +47,7 @@
namespace js {
class NumberObject : public ::JSObject
class NumberObject : public JSObject
{
/* Stores this Number object's [[PrimitiveValue]]. */
static const uintN PRIMITIVE_VALUE_SLOT = 0;

View File

@ -50,11 +50,11 @@
#include "jsstrinlines.h"
#include "RegExpStatics-inl.h"
inline js::RegExpObject *
inline js::RegExpObject &
JSObject::asRegExp()
{
JS_ASSERT(isRegExp());
return static_cast<js::RegExpObject *>(this);
return *static_cast<js::RegExpObject *>(this);
}
namespace js {

View File

@ -98,7 +98,7 @@ RegExpObjectBuilder::getOrCreate()
return false;
obj->setPrivate(NULL);
reobj_ = obj->asRegExp();
reobj_ = &obj->asRegExp();
return true;
}
@ -112,7 +112,7 @@ RegExpObjectBuilder::getOrCreateClone(RegExpObject *proto)
return false;
clone->setPrivate(NULL);
reobj_ = clone->asRegExp();
reobj_ = &clone->asRegExp();
return true;
}
@ -327,9 +327,9 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
if (xdr->mode == JSXDR_ENCODE) {
JS_ASSERT(objp);
RegExpObject *reobj = (*objp)->asRegExp();
source = reobj->getSource();
flagsword = reobj->getFlags();
RegExpObject &reobj = (*objp)->asRegExp();
source = reobj.getSource();
flagsword = reobj.getFlags();
}
if (!JS_XDRString(xdr, &source) || !JS_XDRUint32(xdr, &flagsword))
return false;
@ -360,14 +360,14 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
static void
regexp_finalize(JSContext *cx, JSObject *obj)
{
obj->asRegExp()->finalize(cx);
obj->asRegExp().finalize(cx);
}
static void
regexp_trace(JSTracer *trc, JSObject *obj)
{
if (trc->runtime->gcRunning)
obj->asRegExp()->purge(trc->context);
obj->asRegExp().purge(trc->context);
}
Class js::RegExpClass = {
@ -565,7 +565,7 @@ 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(&obj->asRegExp(), &proto->asRegExp());
}
JSFlatString *

View File

@ -65,7 +65,7 @@ enum RegExpRunStatus
RegExpRunStatus_Success_NotFound
};
class RegExpObject : public ::JSObject
class RegExpObject : public JSObject
{
typedef detail::RegExpPrivate RegExpPrivate;
typedef detail::RegExpPrivateCode RegExpPrivateCode;

345
js/src/vm/ScopeObject-inl.h Normal file
View File

@ -0,0 +1,345 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey call object code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul Biggar <pbiggar@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef ScopeObject_inl_h___
#define ScopeObject_inl_h___
#include "ScopeObject.h"
namespace js {
inline JSObject &
ScopeObject::enclosingScope() const
{
return getReservedSlot(SCOPE_CHAIN_SLOT).toObject();
}
inline bool
ScopeObject::setEnclosingScope(JSContext *cx, JSObject &obj)
{
if (!obj.setDelegate(cx))
return false;
setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(obj));
return true;
}
inline StackFrame *
ScopeObject::maybeStackFrame() const
{
JS_ASSERT(!isStaticBlock());
return reinterpret_cast<StackFrame *>(JSObject::getPrivate());
}
inline void
ScopeObject::setStackFrame(StackFrame *frame)
{
return setPrivate(frame);
}
/*static*/ inline size_t
ScopeObject::offsetOfEnclosingScope()
{
return getFixedSlotOffset(SCOPE_CHAIN_SLOT);
}
inline bool
CallObject::isForEval() const
{
JS_ASSERT(getReservedSlot(CALLEE_SLOT).isObjectOrNull());
JS_ASSERT_IF(getReservedSlot(CALLEE_SLOT).isObject(),
getReservedSlot(CALLEE_SLOT).toObject().isFunction());
return getReservedSlot(CALLEE_SLOT).isNull();
}
inline void
CallObject::setCallee(JSObject *callee)
{
JS_ASSERT_IF(callee, callee->isFunction());
setFixedSlot(CALLEE_SLOT, ObjectOrNullValue(callee));
}
inline JSObject *
CallObject::getCallee() const
{
return getReservedSlot(CALLEE_SLOT).toObjectOrNull();
}
inline JSFunction *
CallObject::getCalleeFunction() const
{
return getReservedSlot(CALLEE_SLOT).toObject().toFunction();
}
inline const Value &
CallObject::getArguments() const
{
JS_ASSERT(!isForEval());
return getReservedSlot(ARGUMENTS_SLOT);
}
inline void
CallObject::setArguments(const Value &v)
{
JS_ASSERT(!isForEval());
setFixedSlot(ARGUMENTS_SLOT, v);
}
inline void
CallObject::initArguments(const Value &v)
{
JS_ASSERT(!isForEval());
initFixedSlot(ARGUMENTS_SLOT, v);
}
inline const Value &
CallObject::arg(uintN i) const
{
JS_ASSERT(i < getCalleeFunction()->nargs);
return getSlot(RESERVED_SLOTS + i);
}
inline void
CallObject::setArg(uintN i, const Value &v)
{
JS_ASSERT(i < getCalleeFunction()->nargs);
setSlot(RESERVED_SLOTS + i, v);
}
inline void
CallObject::initArgUnchecked(uintN i, const Value &v)
{
JS_ASSERT(i < getCalleeFunction()->nargs);
initSlotUnchecked(RESERVED_SLOTS + i, v);
}
inline const Value &
CallObject::var(uintN i) const
{
JSFunction *fun = getCalleeFunction();
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
JS_ASSERT(i < fun->script()->bindings.countVars());
return getSlot(RESERVED_SLOTS + fun->nargs + i);
}
inline void
CallObject::setVar(uintN i, const Value &v)
{
JSFunction *fun = getCalleeFunction();
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
JS_ASSERT(i < fun->script()->bindings.countVars());
setSlot(RESERVED_SLOTS + fun->nargs + i, v);
}
inline void
CallObject::initVarUnchecked(uintN i, const Value &v)
{
JSFunction *fun = getCalleeFunction();
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
JS_ASSERT(i < fun->script()->bindings.countVars());
initSlotUnchecked(RESERVED_SLOTS + fun->nargs + i, v);
}
inline void
CallObject::copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots)
{
JS_ASSERT(slotInRange(RESERVED_SLOTS + nargs + nvars, SENTINEL_ALLOWED));
copySlotRange(RESERVED_SLOTS, argv, nargs);
copySlotRange(RESERVED_SLOTS + nargs, slots, nvars);
}
inline HeapValueArray
CallObject::argArray()
{
DebugOnly<JSFunction*> fun = getCalleeFunction();
JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS, fun->nargs));
return HeapValueArray(getSlotAddress(RESERVED_SLOTS));
}
inline HeapValueArray
CallObject::varArray()
{
JSFunction *fun = getCalleeFunction();
JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS + fun->nargs,
fun->script()->bindings.countVars()));
return HeapValueArray(getSlotAddress(RESERVED_SLOTS + fun->nargs));
}
inline uint32_t
NestedScopeObject::stackDepth() const
{
return getReservedSlot(DEPTH_SLOT).toPrivateUint32();
}
inline JSObject &
WithObject::withThis() const
{
return getReservedSlot(THIS_SLOT).toObject();
}
inline JSObject &
WithObject::object() const
{
return *JSObject::getProto();
}
inline uint32_t
BlockObject::slotCount() const
{
return propertyCount();
}
inline HeapValue &
BlockObject::slotValue(unsigned i)
{
return getSlotRef(RESERVED_SLOTS + i);
}
inline StaticBlockObject *
StaticBlockObject::enclosingBlock() const
{
JSObject *obj = getReservedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
return obj ? &obj->asStaticBlock() : NULL;
}
inline void
StaticBlockObject::setEnclosingBlock(StaticBlockObject *blockObj)
{
setFixedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(blockObj));
}
inline void
StaticBlockObject::setStackDepth(uint32_t depth)
{
JS_ASSERT(getReservedSlot(DEPTH_SLOT).isUndefined());
getReservedSlotRef(DEPTH_SLOT).init(PrivateUint32Value(depth));
}
inline void
StaticBlockObject::setDefinitionParseNode(unsigned i, Definition *def)
{
JS_ASSERT(slotValue(i).isUndefined());
slotValue(i).init(PrivateValue(def));
}
inline Definition *
StaticBlockObject::maybeDefinitionParseNode(unsigned i)
{
Value v = slotValue(i);
return v.isUndefined() ? NULL : reinterpret_cast<Definition *>(v.toPrivate());
}
inline void
StaticBlockObject::poisonDefinitionParseNode(unsigned i)
{
slotValue(i).init(PrivateValue(NULL));
}
inline StaticBlockObject &
ClonedBlockObject::staticBlock() const
{
return getProto()->asStaticBlock();
}
inline const Value &
ClonedBlockObject::closedSlot(unsigned i)
{
JS_ASSERT(!maybeStackFrame());
return slotValue(i);
}
} /* namespace js */
inline js::ScopeObject &
JSObject::asScope()
{
JS_ASSERT(isScope());
return *static_cast<js::ScopeObject *>(this);
}
inline js::CallObject &
JSObject::asCall()
{
JS_ASSERT(isCall());
return *static_cast<js::CallObject *>(this);
}
inline js::DeclEnvObject &
JSObject::asDeclEnv()
{
JS_ASSERT(isDeclEnv());
return *static_cast<js::DeclEnvObject *>(this);
}
inline js::NestedScopeObject &
JSObject::asNestedScope()
{
JS_ASSERT(isWith() || isBlock());
return *static_cast<js::NestedScopeObject *>(this);
}
inline js::WithObject &
JSObject::asWith()
{
JS_ASSERT(isWith());
return *static_cast<js::WithObject *>(this);
}
inline js::BlockObject &
JSObject::asBlock()
{
JS_ASSERT(isBlock());
return *static_cast<js::BlockObject *>(this);
}
inline js::StaticBlockObject &
JSObject::asStaticBlock()
{
JS_ASSERT(isStaticBlock());
return *static_cast<js::StaticBlockObject *>(this);
}
inline js::ClonedBlockObject &
JSObject::asClonedBlock()
{
JS_ASSERT(isClonedBlock());
return *static_cast<js::ClonedBlockObject *>(this);
}
#endif /* CallObject_inl_h___ */

737
js/src/vm/ScopeObject.cpp Normal file
View File

@ -0,0 +1,737 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey call object code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul Biggar <pbiggar@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "jscompartment.h"
#include "jsiter.h"
#include "jsscope.h"
#if JS_HAS_XDR
#include "jsxdrapi.h"
#endif
#include "GlobalObject.h"
#include "ScopeObject.h"
#include "jsatominlines.h"
#include "jsobjinlines.h"
#include "ScopeObject-inl.h"
using namespace js;
using namespace js::types;
/*
* Construct a call object for the given bindings. If this is a call object
* for a function invocation, callee should be the function being called.
* Otherwise it must be a call object for eval of strict mode code, and callee
* must be null.
*/
CallObject *
CallObject::create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObject *callee)
{
Bindings &bindings = script->bindings;
gc::AllocKind kind = gc::GetGCObjectKind(bindings.lastShape()->numFixedSlots() + 1);
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
HeapValue *slots;
if (!PreallocateObjectDynamicSlots(cx, bindings.lastShape(), &slots))
return NULL;
RootedVarShape shape(cx);
shape = bindings.lastShape();
JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
if (!obj)
return NULL;
/*
* Update the parent for bindings associated with non-compileAndGo scripts,
* whose call objects do not have a consistent global variable and need
* to be updated dynamically.
*/
JSObject &global = enclosing.global();
if (&global != obj->getParent()) {
JS_ASSERT(obj->getParent() == NULL);
if (!obj->setParent(cx, &global))
return NULL;
}
#ifdef DEBUG
JS_ASSERT(!obj->inDictionaryMode());
for (Shape::Range r = obj->lastProperty(); !r.empty(); r.popFront()) {
const Shape &s = r.front();
if (s.hasSlot()) {
JS_ASSERT(s.slot() + 1 == obj->slotSpan());
break;
}
}
#endif
if (!obj->asScope().setEnclosingScope(cx, enclosing))
return NULL;
JS_ASSERT_IF(callee, callee->isFunction());
obj->initFixedSlot(CALLEE_SLOT, ObjectOrNullValue(callee));
/*
* 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;
return &obj->asCall();
}
Class js::DeclEnvClass = {
js_Object_str,
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(DeclEnvObject::RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub
};
DeclEnvObject *
DeclEnvObject::create(JSContext *cx, StackFrame *fp)
{
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
RootedVarShape emptyDeclEnvShape(cx);
emptyDeclEnvShape = EmptyShape::getInitialShape(cx, &DeclEnvClass, NULL,
&fp->scopeChain().global(),
FINALIZE_KIND);
if (!emptyDeclEnvShape)
return NULL;
JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyDeclEnvShape, type, NULL);
if (!obj)
return NULL;
obj->setPrivate(fp);
if (!obj->asScope().setEnclosingScope(cx, fp->scopeChain()))
return NULL;
return &obj->asDeclEnv();
}
WithObject *
WithObject::create(JSContext *cx, StackFrame *fp, JSObject &proto, JSObject &enclosing,
uint32_t depth)
{
RootedVarTypeObject type(cx);
type = proto.getNewType(cx);
if (!type)
return NULL;
RootedVarShape emptyWithShape(cx);
emptyWithShape = EmptyShape::getInitialShape(cx, &WithClass, &proto,
&enclosing.global(), FINALIZE_KIND);
if (!emptyWithShape)
return NULL;
JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyWithShape, type, NULL);
if (!obj)
return NULL;
if (!obj->asScope().setEnclosingScope(cx, enclosing))
return NULL;
obj->setReservedSlot(DEPTH_SLOT, PrivateUint32Value(depth));
obj->setPrivate(js_FloatingFrameIfGenerator(cx, fp));
JSObject *thisp = proto.thisObject(cx);
if (!thisp)
return NULL;
obj->setFixedSlot(THIS_SLOT, ObjectValue(*thisp));
return &obj->asWith();
}
static JSBool
with_LookupGeneric(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp)
{
/* Fixes bug 463997 */
uintN flags = cx->resolveFlags;
if (flags == RESOLVE_INFER)
flags = js_InferFlags(cx, flags);
flags |= JSRESOLVE_WITH;
JSAutoResolveFlags rf(cx, flags);
return obj->asWith().object().lookupGeneric(cx, id, objp, propp);
}
static JSBool
with_LookupProperty(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp, JSProperty **propp)
{
return with_LookupGeneric(cx, obj, ATOM_TO_JSID(name), objp, propp);
}
static JSBool
with_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
JSProperty **propp)
{
jsid id;
if (!IndexToId(cx, index, &id))
return false;
return with_LookupGeneric(cx, obj, id, objp, propp);
}
static JSBool
with_LookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, JSProperty **propp)
{
return with_LookupGeneric(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
}
static JSBool
with_GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
{
return obj->asWith().object().getGeneric(cx, id, vp);
}
static JSBool
with_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp)
{
return with_GetGeneric(cx, obj, receiver, ATOM_TO_JSID(name), vp);
}
static JSBool
with_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp)
{
jsid id;
if (!IndexToId(cx, index, &id))
return false;
return with_GetGeneric(cx, obj, receiver, id, vp);
}
static JSBool
with_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
{
return with_GetGeneric(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
}
static JSBool
with_SetGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
{
return obj->asWith().object().setGeneric(cx, id, vp, strict);
}
static JSBool
with_SetProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
{
return obj->asWith().object().setProperty(cx, name, vp, strict);
}
static JSBool
with_SetElement(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict)
{
return obj->asWith().object().setElement(cx, index, vp, strict);
}
static JSBool
with_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
{
return obj->asWith().object().setSpecial(cx, sid, vp, strict);
}
static JSBool
with_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
{
return obj->asWith().object().getGenericAttributes(cx, id, attrsp);
}
static JSBool
with_GetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
{
return obj->asWith().object().getPropertyAttributes(cx, name, attrsp);
}
static JSBool
with_GetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, uintN *attrsp)
{
return obj->asWith().object().getElementAttributes(cx, index, attrsp);
}
static JSBool
with_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
{
return obj->asWith().object().getSpecialAttributes(cx, sid, attrsp);
}
static JSBool
with_SetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
{
return obj->asWith().object().setGenericAttributes(cx, id, attrsp);
}
static JSBool
with_SetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
{
return obj->asWith().object().setPropertyAttributes(cx, name, attrsp);
}
static JSBool
with_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, uintN *attrsp)
{
return obj->asWith().object().setElementAttributes(cx, index, attrsp);
}
static JSBool
with_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
{
return obj->asWith().object().setSpecialAttributes(cx, sid, attrsp);
}
static JSBool
with_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
{
return obj->asWith().object().deleteGeneric(cx, id, rval, strict);
}
static JSBool
with_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
return obj->asWith().object().deleteProperty(cx, name, rval, strict);
}
static JSBool
with_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict)
{
return obj->asWith().object().deleteElement(cx, index, rval, strict);
}
static JSBool
with_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
{
return obj->asWith().object().deleteSpecial(cx, sid, rval, strict);
}
static JSBool
with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
Value *statep, jsid *idp)
{
return obj->asWith().object().enumerate(cx, enum_op, statep, idp);
}
static JSType
with_TypeOf(JSContext *cx, JSObject *obj)
{
return JSTYPE_OBJECT;
}
static JSObject *
with_ThisObject(JSContext *cx, JSObject *obj)
{
return &obj->asWith().withThis();
}
Class js::WithClass = {
"With",
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(WithObject::RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS,
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
NULL, /* finalize */
NULL, /* reserved */
NULL, /* checkAccess */
NULL, /* call */
NULL, /* construct */
NULL, /* xdrObject */
NULL, /* hasInstance */
NULL, /* trace */
JS_NULL_CLASS_EXT,
{
with_LookupGeneric,
with_LookupProperty,
with_LookupElement,
with_LookupSpecial,
NULL, /* defineGeneric */
NULL, /* defineProperty */
NULL, /* defineElement */
NULL, /* defineSpecial */
with_GetGeneric,
with_GetProperty,
with_GetElement,
NULL, /* getElementIfPresent */
with_GetSpecial,
with_SetGeneric,
with_SetProperty,
with_SetElement,
with_SetSpecial,
with_GetGenericAttributes,
with_GetPropertyAttributes,
with_GetElementAttributes,
with_GetSpecialAttributes,
with_SetGenericAttributes,
with_SetPropertyAttributes,
with_SetElementAttributes,
with_SetSpecialAttributes,
with_DeleteGeneric,
with_DeleteProperty,
with_DeleteElement,
with_DeleteSpecial,
with_Enumerate,
with_TypeOf,
NULL, /* fix */
with_ThisObject,
NULL, /* clear */
}
};
ClonedBlockObject *
ClonedBlockObject::create(JSContext *cx, StaticBlockObject &block, StackFrame *fp)
{
RootedVarTypeObject type(cx);
type = block.getNewType(cx);
if (!type)
return NULL;
HeapValue *slots;
if (!PreallocateObjectDynamicSlots(cx, block.lastProperty(), &slots))
return NULL;
RootedVarShape shape(cx);
shape = block.lastProperty();
JSObject *obj = JSObject::create(cx, FINALIZE_KIND, shape, type, slots);
if (!obj)
return NULL;
/* Set the parent if necessary, as for call objects. */
JSObject &global = fp->scopeChain().global();
if (&global != obj->getParent()) {
JS_ASSERT(obj->getParent() == NULL);
if (!obj->setParent(cx, &global))
return NULL;
}
JS_ASSERT(!obj->inDictionaryMode());
JS_ASSERT(obj->slotSpan() >= block.slotCount() + RESERVED_SLOTS);
obj->setReservedSlot(DEPTH_SLOT, PrivateUint32Value(block.stackDepth()));
obj->setPrivate(js_FloatingFrameIfGenerator(cx, fp));
if (obj->lastProperty()->extensibleParents() && !obj->generateOwnShape(cx))
return NULL;
return &obj->asClonedBlock();
}
bool
ClonedBlockObject::put(JSContext *cx, JSBool normalUnwind)
{
StackFrame *fp = cx->fp();
JS_ASSERT(maybeStackFrame() == js_FloatingFrameIfGenerator(cx, fp));
uint32_t count = slotCount();
uint32_t depth = stackDepth();
/* The block and its locals must be on the current stack for GC safety. */
JS_ASSERT(depth <= uint32_t(cx->regs().sp - fp->base()));
JS_ASSERT(count <= uint32_t(cx->regs().sp - fp->base() - depth));
/* See comments in CheckDestructuring in frontend/Parser.cpp. */
JS_ASSERT(count >= 1);
if (normalUnwind)
copySlotRange(RESERVED_SLOTS, fp->base() + depth, count);
/* We must clear the private slot even with errors. */
setPrivate(NULL);
fp->setScopeChainNoCallObj(enclosingScope());
return normalUnwind;
}
static JSBool
block_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
/*
* Block objects are never exposed to script, and the engine handles them
* with care. So unlike other getters, this one can assert (rather than
* check) certain invariants about obj.
*/
ClonedBlockObject &block = obj->asClonedBlock();
uintN index = (uintN) JSID_TO_INT(id);
JS_ASSERT(index < block.slotCount());
if (StackFrame *fp = block.maybeStackFrame()) {
fp = js_LiveFrameIfGenerator(fp);
index += fp->numFixed() + block.stackDepth();
JS_ASSERT(index < fp->numSlots());
*vp = fp->slots()[index];
return true;
}
/* Values are in slots immediately following the class-reserved ones. */
JS_ASSERT(block.closedSlot(index) == *vp);
return true;
}
static JSBool
block_setProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
{
ClonedBlockObject &block = obj->asClonedBlock();
uintN index = (uintN) JSID_TO_INT(id);
JS_ASSERT(index < block.slotCount());
if (StackFrame *fp = block.maybeStackFrame()) {
fp = js_LiveFrameIfGenerator(fp);
index += fp->numFixed() + block.stackDepth();
JS_ASSERT(index < fp->numSlots());
fp->slots()[index] = *vp;
return true;
}
/*
* The value in *vp will be written back to the slot in obj that was
* allocated when this let binding was defined.
*/
return true;
}
StaticBlockObject *
StaticBlockObject::create(JSContext *cx)
{
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
RootedVarShape emptyBlockShape(cx);
emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockClass, NULL, NULL, FINALIZE_KIND);
if (!emptyBlockShape)
return NULL;
JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyBlockShape, type, NULL);
if (!obj)
return NULL;
return &obj->asStaticBlock();
}
const Shape *
StaticBlockObject::addVar(JSContext *cx, jsid id, intN index, bool *redeclared)
{
*redeclared = false;
/* Inline JSObject::addProperty in order to trap the redefinition case. */
Shape **spp;
if (Shape::search(cx, lastProperty(), id, &spp, true)) {
*redeclared = true;
return NULL;
}
/*
* Don't convert this object to dictionary mode so that we can clone the
* block's shape later.
*/
uint32_t slot = JSSLOT_FREE(&BlockClass) + index;
return addPropertyInternal(cx, id, block_getProperty, block_setProperty,
slot, JSPROP_ENUMERATE | JSPROP_PERMANENT,
Shape::HAS_SHORTID, index, spp,
/* allowDictionary = */ false);
}
Class js::BlockClass = {
"Block",
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(BlockObject::RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS,
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub
};
#if JS_HAS_XDR
#define NO_PARENT_INDEX UINT32_MAX
static uint32_t
FindObjectIndex(JSObjectArray *array, JSObject *obj)
{
size_t i;
if (array) {
i = array->length;
do {
if (array->vector[--i] == obj)
return i;
} while (i != 0);
}
return NO_PARENT_INDEX;
}
bool
js_XDRStaticBlockObject(JSXDRState *xdr, StaticBlockObject **objp)
{
JSContext *cx;
uint32_t parentId;
StaticBlockObject *obj, *parent;
uintN depth, count;
uint32_t depthAndCount;
const Shape *shape;
cx = xdr->cx;
#ifdef __GNUC__
obj = NULL; /* quell GCC overwarning */
#endif
if (xdr->mode == JSXDR_ENCODE) {
obj = *objp;
parent = obj->enclosingBlock();
parentId = JSScript::isValidOffset(xdr->script->objectsOffset)
? FindObjectIndex(xdr->script->objects(), parent)
: NO_PARENT_INDEX;
depth = uint16_t(obj->stackDepth());
count = uint16_t(obj->slotCount());
depthAndCount = uint32_t(depth << 16) | count;
}
#ifdef __GNUC__ /* suppress bogus gcc warnings */
else count = 0;
#endif
/* First, XDR the parent atomid. */
if (!JS_XDRUint32(xdr, &parentId))
return JS_FALSE;
if (xdr->mode == JSXDR_DECODE) {
obj = StaticBlockObject::create(cx);
if (!obj)
return JS_FALSE;
*objp = obj;
/*
* If there's a parent id, then get the parent out of our script's
* object array. We know that we XDR block object in outer-to-inner
* order, which means that getting the parent now will work.
*/
if (parentId == NO_PARENT_INDEX)
parent = NULL;
else
parent = &xdr->script->getObject(parentId)->asStaticBlock();
obj->setEnclosingBlock(parent);
}
AutoObjectRooter tvr(cx, obj);
if (!JS_XDRUint32(xdr, &depthAndCount))
return false;
if (xdr->mode == JSXDR_DECODE) {
depth = uint16_t(depthAndCount >> 16);
count = uint16_t(depthAndCount);
obj->setStackDepth(depth);
/*
* XDR the block object's properties. We know that there are 'count'
* properties to XDR, stored as id/shortid pairs.
*/
for (uintN i = 0; i < count; i++) {
JSAtom *atom;
/* XDR the real id. */
if (!js_XDRAtom(xdr, &atom))
return false;
bool redeclared;
if (!obj->addVar(cx, ATOM_TO_JSID(atom), i, &redeclared)) {
JS_ASSERT(!redeclared);
return false;
}
}
} else {
AutoShapeVector shapes(cx);
shapes.growBy(count);
for (Shape::Range r(obj->lastProperty()); !r.empty(); r.popFront()) {
shape = &r.front();
shapes[shape->shortid()] = shape;
}
/*
* XDR the block object's properties. We know that there are 'count'
* properties to XDR, stored as id/shortid pairs.
*/
for (uintN i = 0; i < count; i++) {
shape = shapes[i];
JS_ASSERT(shape->getter() == block_getProperty);
jsid propid = shape->propid();
JS_ASSERT(JSID_IS_ATOM(propid));
JSAtom *atom = JSID_TO_ATOM(propid);
#ifdef DEBUG
uint16_t shortid = uint16_t(shape->shortid());
JS_ASSERT(shortid == i);
#endif
/* XDR the real id. */
if (!js_XDRAtom(xdr, &atom))
return false;
}
}
return true;
}
#endif /* JS_HAS_XDR */

264
js/src/vm/ScopeObject.h Normal file
View File

@ -0,0 +1,264 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey call object code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul Biggar <pbiggar@mozilla.com> (original author)
* Luke Wagner <luke@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef ScopeObject_h___
#define ScopeObject_h___
#include "jsobj.h"
namespace js {
/*
* Scope objects
*
* Scope objects are technically real JSObjects but only belong on the scope
* chain (that is, fp->scopeChain() or fun->environment()). The hierarchy of
* scope objects is:
*
* JSObject Generic object
* \
* ScopeObject Engine-internal scope
* \ \ \
* \ \ DeclEnvObject Holds name of recursive/heavyweight named lambda
* \ \
* \ CallObject Scope of entire function or strict eval
* \
* NestedScopeObject Scope created for a statement
* \ \
* \ WithObject with
* \
* BlockObject Shared interface of cloned/static block objects
* \ \
* \ ClonedBlockObject let, switch, catch, for
* \
* StaticBlockObject See NB
*
* This hierarchy represents more than just the interface hierarchy: reserved
* slots in base classes are fixed for all derived classes. Thus, for example,
* ScopeObject::enclosingScope() can simply access a fixed slot without further
* dynamic type information.
*
* NB: Static block objects are a special case: these objects are created at
* compile time to hold the shape/binding information from which block objects
* are cloned at runtime. These objects should never escape into the wild and
* support a restricted set of ScopeObject operations.
*/
class ScopeObject : public JSObject
{
/* Use maybeStackFrame() instead. */
void *getPrivate() const;
protected:
static const uint32_t SCOPE_CHAIN_SLOT = 0;
public:
/*
* Since every scope chain terminates with a global object and GlobalObject
* does not derive ScopeObject (it has a completely different layout), the
* enclosing scope of a ScopeObject is necessarily non-null.
*/
inline JSObject &enclosingScope() const;
inline bool setEnclosingScope(JSContext *cx, JSObject &obj);
/*
* The stack frame for this scope object, if the frame is still active.
* Note: these members may not be called for a StaticBlockObject.
*/
inline js::StackFrame *maybeStackFrame() const;
inline void setStackFrame(StackFrame *frame);
/* For jit access. */
static inline size_t offsetOfEnclosingScope();
};
class CallObject : public ScopeObject
{
static const uint32_t CALLEE_SLOT = 1;
static const uint32_t ARGUMENTS_SLOT = 2;
public:
static const uint32_t RESERVED_SLOTS = 3;
static CallObject *
create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObject *callee);
/* True if this is for a strict mode eval frame or for a function call. */
inline bool isForEval() const;
/*
* The callee function if this CallObject was created for a function
* invocation, or null if it was created for a strict mode eval frame.
*/
inline JSObject *getCallee() const;
inline JSFunction *getCalleeFunction() const;
inline void setCallee(JSObject *callee);
/* Returns the callee's arguments object. */
inline const js::Value &getArguments() const;
inline void setArguments(const js::Value &v);
inline void initArguments(const js::Value &v);
/* Returns the formal argument at the given index. */
inline const js::Value &arg(uintN i) const;
inline void setArg(uintN i, const js::Value &v);
inline void initArgUnchecked(uintN i, const js::Value &v);
/* Returns the variable at the given index. */
inline const js::Value &var(uintN i) const;
inline void setVar(uintN i, const js::Value &v);
inline void initVarUnchecked(uintN i, const js::Value &v);
/*
* Get the actual arrays of arguments and variables. Only call if type
* inference is enabled, where we ensure that call object variables are in
* contiguous slots (see NewCallObject).
*/
inline js::HeapValueArray argArray();
inline js::HeapValueArray varArray();
inline void copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots);
};
class DeclEnvObject : public ScopeObject
{
public:
static const uint32_t RESERVED_SLOTS = 1;
static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT2;
static DeclEnvObject *create(JSContext *cx, StackFrame *fp);
};
class NestedScopeObject : public ScopeObject
{
protected:
static const unsigned DEPTH_SLOT = 1;
public:
/* Return the abstract stack depth right before entering this nested scope. */
uint32_t stackDepth() const;
};
class WithObject : public NestedScopeObject
{
static const unsigned THIS_SLOT = 2;
/* Use WithObject::object() instead. */
JSObject *getProto() const;
public:
static const unsigned RESERVED_SLOTS = 3;
static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT4;
static WithObject *
create(JSContext *cx, StackFrame *fp, JSObject &proto, JSObject &enclosing, uint32_t depth);
/* Return object for the 'this' class hook. */
JSObject &withThis() const;
/* Return the 'o' in 'with (o)'. */
JSObject &object() const;
};
class BlockObject : public NestedScopeObject
{
public:
static const unsigned RESERVED_SLOTS = 2;
static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT4;
/* Return the number of variables associated with this block. */
inline uint32_t slotCount() const;
protected:
/* Blocks contain an object slot for each slot i: 0 <= i < slotCount. */
inline HeapValue &slotValue(unsigned i);
};
class StaticBlockObject : public BlockObject
{
/* These ScopeObject operations are not valid on a static block object. */
js::StackFrame *maybeStackFrame() const;
void setStackFrame(StackFrame *frame);
public:
static StaticBlockObject *create(JSContext *cx);
inline StaticBlockObject *enclosingBlock() const;
inline void setEnclosingBlock(StaticBlockObject *blockObj);
void setStackDepth(uint32_t depth);
/*
* Frontend compilation temporarily uses the object's slots to link
* a let var to its associated Definition parse node.
*/
void setDefinitionParseNode(unsigned i, Definition *def);
Definition *maybeDefinitionParseNode(unsigned i);
void poisonDefinitionParseNode(unsigned i);
const js::Shape *addVar(JSContext *cx, jsid id, intN index, bool *redeclared);
};
class ClonedBlockObject : public BlockObject
{
public:
static ClonedBlockObject *create(JSContext *cx, StaticBlockObject &block, StackFrame *fp);
/* The static block from which this block was cloned. */
StaticBlockObject &staticBlock() const;
/*
* When this block's stack slots are about to be popped, 'put' must be
* called to copy the slot values into this block's object slots.
*/
bool put(JSContext *cx, JSBool normalUnwind);
/* Assuming 'put' has been called, return the value of the ith let var. */
const Value &closedSlot(unsigned i);
};
} /* namespace js */
extern bool
js_XDRStaticBlockObject(JSXDRState *xdr, js::StaticBlockObject **objp);
#endif /* ScopeObject_h___ */

View File

@ -44,13 +44,14 @@
#include "jscntxt.h"
#include "jscompartment.h"
#include "Stack.h"
#include "methodjit/MethodJIT.h"
#include "vm/Stack.h"
#include "jsscriptinlines.h"
#include "ArgumentsObject-inl.h"
#include "CallObject-inl.h"
#include "methodjit/MethodJIT.h"
#include "ArgumentsObject-inl.h"
#include "ScopeObject-inl.h"
namespace js {
@ -84,7 +85,7 @@ StackFrame::varObj()
{
JSObject *obj = &scopeChain();
while (!obj->isVarObj())
obj = obj->scopeChain();
obj = obj->enclosingScope();
return *obj;
}
@ -377,10 +378,10 @@ StackFrame::setScopeChainNoCallObj(JSObject &obj)
if (hasCallObj()) {
JSObject *pobj = &obj;
while (pobj && pobj->getPrivate() != this)
pobj = pobj->scopeChain();
pobj = pobj->enclosingScope();
JS_ASSERT(pobj);
} else {
for (JSObject *pobj = &obj; pobj->isInternalScope(); pobj = pobj->scopeChain())
for (JSObject *pobj = &obj; pobj->isScope(); pobj = pobj->enclosingScope())
JS_ASSERT_IF(pobj->isCall(), pobj->getPrivate() != this);
}
}
@ -405,7 +406,7 @@ StackFrame::callObj() const
JSObject *pobj = &scopeChain();
while (JS_UNLIKELY(!pobj->isCall()))
pobj = pobj->scopeChain();
pobj = pobj->enclosingScope();
return pobj->asCall();
}
@ -477,7 +478,7 @@ StackFrame::markFunctionEpilogueDone()
*/
scopeChain_ = isFunctionFrame()
? callee().toFunction()->environment()
: scopeChain_->internalScopeChain();
: &scopeChain_->asScope().enclosingScope();
flags_ &= ~HAS_CALL_OBJ;
}
}

View File

@ -148,13 +148,12 @@ StackFrame::stealFrameAndSlots(Value *vp, StackFrame *otherfp,
* js_LiveFrameToFloating comment in jsiter.h.
*/
if (hasCallObj()) {
JSObject &obj = callObj();
obj.setPrivate(this);
CallObject &obj = callObj();
obj.setStackFrame(this);
otherfp->flags_ &= ~HAS_CALL_OBJ;
if (js_IsNamedLambda(fun())) {
JSObject *env = obj.internalScopeChain();
JS_ASSERT(env->isDeclEnv());
env->setPrivate(this);
DeclEnvObject &env = obj.enclosingScope().asDeclEnv();
env.setStackFrame(this);
}
}
if (hasArgsObj()) {

View File

@ -73,6 +73,7 @@ class FrameRegsIter;
class AllFramesIter;
class ArgumentsObject;
class StaticBlockObject;
#ifdef JS_METHODJIT
typedef js::mjit::CallSite JSInlinedSite;
@ -369,7 +370,7 @@ class StackFrame
/* Lazily initialized */
Value rval_; /* return value of the frame */
JSObject *blockChain_; /* innermost let block */
StaticBlockObject *blockChain_; /* innermost let block */
jsbytecode *prevpc_; /* pc of previous frame*/
JSInlinedSite *prevInline_; /* inlined site in previous frame */
void *hookData_; /* closure returned by call hook */
@ -848,16 +849,16 @@ class StackFrame
return (flags_ & HAS_BLOCKCHAIN) && blockChain_;
}
JSObject *maybeBlockChain() {
StaticBlockObject *maybeBlockChain() {
return (flags_ & HAS_BLOCKCHAIN) ? blockChain_ : NULL;
}
JSObject &blockChain() const {
StaticBlockObject &blockChain() const {
JS_ASSERT(hasBlockChain());
return *blockChain_;
}
void setBlockChain(JSObject *obj) {
void setBlockChain(StaticBlockObject *obj) {
flags_ |= HAS_BLOCKCHAIN;
blockChain_ = obj;
}

View File

@ -43,11 +43,11 @@
#include "StringObject.h"
inline js::StringObject *
inline js::StringObject &
JSObject::asString()
{
JS_ASSERT(isString());
return static_cast<js::StringObject *>(const_cast<JSObject *>(this));
return *static_cast<js::StringObject *>(this);
}
namespace js {
@ -82,10 +82,10 @@ StringObject::create(JSContext *cx, JSString *str)
JSObject *obj = NewBuiltinClassInstance(cx, &StringClass);
if (!obj)
return NULL;
StringObject *strobj = obj->asString();
if (!strobj->init(cx, str))
StringObject &strobj = obj->asString();
if (!strobj.init(cx, str))
return NULL;
return strobj;
return &strobj;
}
inline StringObject *
@ -94,10 +94,10 @@ StringObject::createWithProto(JSContext *cx, JSString *str, JSObject &proto)
JSObject *obj = NewObjectWithClassProto(cx, &StringClass, &proto, NULL);
if (!obj)
return NULL;
StringObject *strobj = obj->asString();
if (!strobj->init(cx, str))
StringObject &strobj = obj->asString();
if (!strobj.init(cx, str))
return NULL;
return strobj;
return &strobj;
}
} // namespace js

View File

@ -48,7 +48,7 @@
namespace js {
class StringObject : public ::JSObject
class StringObject : public JSObject
{
static const uintN PRIMITIVE_THIS_SLOT = 0;
static const uintN LENGTH_SLOT = 1;