Bug 885758 - Add ExclusiveContext for use by threads with exclusive access to their compartment, r=billm.

This commit is contained in:
Brian Hackett 2013-07-10 09:29:52 -06:00
parent 63ed0e9589
commit aafb978437
95 changed files with 1935 additions and 1464 deletions

View File

@ -512,7 +512,7 @@ struct GCMethods<T *>
#endif
};
#if defined(DEBUG) && defined(JS_THREADSAFE)
#if defined(DEBUG)
/* This helper allows us to assert that Rooted<T> is scoped within a request. */
extern JS_PUBLIC_API(bool)
IsInRequest(JSContext *cx);
@ -533,21 +533,16 @@ namespace JS {
template <typename T>
class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
{
void init(JSContext *cxArg) {
MOZ_ASSERT(cxArg);
#ifdef JS_THREADSAFE
MOZ_ASSERT(js::IsInRequest(cxArg));
#endif
/* Note: CX is a subclass of either ContextFriendFields or PerThreadDataFriendFields. */
template <typename CX>
void init(CX *cx) {
#ifdef JSGC_TRACK_EXACT_ROOTS
js::ContextFriendFields *cx = js::ContextFriendFields::get(cxArg);
commonInit(cx->thingGCRooters);
#endif
}
js::ThingRootKind kind = js::GCMethods<T>::kind();
this->stack = &cx->thingGCRooters[kind];
this->prev = *stack;
*stack = reinterpret_cast<Rooted<void*>*>(this);
void init(js::PerThreadDataFriendFields *pt) {
MOZ_ASSERT(pt);
#ifdef JSGC_TRACK_EXACT_ROOTS
commonInit(pt->thingGCRooters);
JS_ASSERT(!js::GCMethods<T>::poisoned(ptr));
#endif
}
@ -557,7 +552,8 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
: ptr(js::GCMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(cx);
MOZ_ASSERT(js::IsInRequest(cx));
init(js::ContextFriendFields::get(cx));
}
Rooted(JSContext *cx, T initial
@ -565,23 +561,40 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
: ptr(initial)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(cx);
MOZ_ASSERT(js::IsInRequest(cx));
init(js::ContextFriendFields::get(cx));
}
Rooted(js::PerThreadData *pt
Rooted(js::ContextFriendFields *cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(js::GCMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(js::PerThreadDataFriendFields::get(pt));
init(cx);
}
Rooted(js::PerThreadData *pt, T initial
Rooted(js::ContextFriendFields *cx, T initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(js::PerThreadDataFriendFields::get(pt));
init(cx);
}
Rooted(js::PerThreadDataFriendFields *pt
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(js::GCMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
Rooted(js::PerThreadDataFriendFields *pt, T initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
Rooted(JSRuntime *rt
@ -642,20 +655,6 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
bool operator==(const T &other) const { return ptr == other; }
private:
void commonInit(Rooted<void*> **thingGCRooters) {
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
scanned = false;
#endif
#ifdef JSGC_TRACK_EXACT_ROOTS
js::ThingRootKind kind = js::GCMethods<T>::kind();
this->stack = &thingGCRooters[kind];
this->prev = *stack;
*stack = reinterpret_cast<Rooted<void*>*>(this);
JS_ASSERT(!js::GCMethods<T>::poisoned(ptr));
#endif
}
#ifdef JSGC_TRACK_EXACT_ROOTS
Rooted<void*> **stack, *prev;
#endif
@ -713,8 +712,9 @@ class SkipRoot
const uint8_t *start;
const uint8_t *end;
template <typename T>
void init(SkipRoot **head, const T *ptr, size_t count) {
template <typename CX, typename T>
void init(CX *cx, const T *ptr, size_t count) {
SkipRoot **head = &cx->skipGCRooters;
this->stack = head;
this->prev = *stack;
*stack = this;
@ -723,23 +723,6 @@ class SkipRoot
}
public:
template <typename T>
SkipRoot(JSContext *cx, const T *ptr, size_t count = 1
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
init(&ContextFriendFields::get(cx)->skipGCRooters, ptr, count);
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
template <typename T>
SkipRoot(js::PerThreadData *ptd, const T *ptr, size_t count = 1
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
PerThreadDataFriendFields *ptff = PerThreadDataFriendFields::get(ptd);
init(&ptff->skipGCRooters, ptr, count);
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
~SkipRoot() {
JS_ASSERT(*stack == this);
*stack = prev;
@ -753,22 +736,36 @@ class SkipRoot
#else /* DEBUG && JSGC_ROOT_ANALYSIS */
template <typename T>
void init(js::ContextFriendFields *cx, const T *ptr, size_t count) {}
public:
#endif /* DEBUG && JSGC_ROOT_ANALYSIS */
template <typename T>
SkipRoot(JSContext *cx, const T *ptr, size_t count = 1
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
init(ContextFriendFields::get(cx), ptr, count);
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
template <typename T>
SkipRoot(PerThreadData *ptd, const T *ptr, size_t count = 1
SkipRoot(ContextFriendFields *cx, const T *ptr, size_t count = 1
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
init(cx, ptr, count);
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
#endif /* DEBUG && JSGC_ROOT_ANALYSIS */
template <typename T>
SkipRoot(PerThreadData *pt, const T *ptr, size_t count = 1
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
init(PerThreadDataFriendFields::get(pt), ptr, count);
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
@ -778,15 +775,17 @@ template <typename T>
class FakeRooted : public RootedBase<T>
{
public:
FakeRooted(JSContext *cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
template <typename CX>
FakeRooted(CX *cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(GCMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
FakeRooted(JSContext *cx, T initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
template <typename CX>
FakeRooted(CX *cx, T initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;

View File

@ -35,7 +35,7 @@ Module::setScript(JSScript *script)
}
Module *
Module::create(JSContext *cx, HandleAtom atom)
Module::create(ExclusiveContext *cx, HandleAtom atom)
{
RootedObject object(cx, NewBuiltinClassInstance(cx, &class_));
if (!object)

View File

@ -13,7 +13,7 @@ namespace js {
class Module : public JSObject {
public:
static Module *create(JSContext *cx, js::HandleAtom atom);
static Module *create(ExclusiveContext *cx, js::HandleAtom atom);
JSAtom *atom() {
return &getReservedSlot(ATOM_SLOT).toString()->asAtom();

View File

@ -15,6 +15,7 @@
#include "vm/StringBuffer.h"
#include "jsobjinlines.h"
#include "jsstrinlines.h"
using namespace js;
using namespace js::types;

View File

@ -179,16 +179,19 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
if (canLazilyParse) {
syntaxParser.construct(cx, options, chars, length, /* foldConstants = */ false,
syntaxParser.construct(cx, &cx->tempLifoAlloc(),
options, chars, length, /* foldConstants = */ false,
(Parser<SyntaxParseHandler> *) NULL,
(LazyScript *) NULL);
}
Parser<FullParseHandler> parser(cx, options, chars, length, /* foldConstants = */ true,
Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(),
options, chars, length, /* foldConstants = */ true,
canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
parser.sct = sct;
GlobalSharedContext globalsc(cx, scopeChain, StrictModeFromContext(cx));
GlobalSharedContext globalsc(cx, scopeChain,
options.strictOption, options.extraWarningsOption);
bool savedCallerFun =
options.compileAndGo &&
@ -354,7 +357,7 @@ frontend::CompileLazyFunction(JSContext *cx, HandleFunction fun, LazyScript *laz
.setNoScriptRval(false)
.setSelfHostingMode(false);
Parser<FullParseHandler> parser(cx, options, chars, length,
Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options, chars, length,
/* foldConstants = */ true, NULL, lazy);
uint32_t staticLevel = lazy->staticLevel(cx);
@ -422,14 +425,16 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
if (canLazilyParse) {
syntaxParser.construct(cx, options, chars, length, /* foldConstants = */ false,
syntaxParser.construct(cx, &cx->tempLifoAlloc(),
options, chars, length, /* foldConstants = */ false,
(Parser<SyntaxParseHandler> *) NULL,
(LazyScript *) NULL);
}
JS_ASSERT(!options.forEval);
Parser<FullParseHandler> parser(cx, options, chars, length, /* foldConstants = */ true,
Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(),
options, chars, length, /* foldConstants = */ true,
canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
parser.sct = &sct;
@ -465,7 +470,7 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
// directive, we backup and reparse it as strict.
TokenStream::Position start(parser.keepAtoms);
parser.tokenStream.tell(&start);
bool strict = StrictModeFromContext(cx);
bool strict = options.strictOption;
bool becameStrict;
FunctionBox *funbox;
ParseNode *pn;

View File

@ -49,7 +49,7 @@ using mozilla::DoubleIsInt32;
using mozilla::PodCopy;
static bool
SetSrcNoteOffset(JSContext *cx, BytecodeEmitter *bce, unsigned index, unsigned which, ptrdiff_t offset);
SetSrcNoteOffset(ExclusiveContext *cx, BytecodeEmitter *bce, unsigned index, unsigned which, ptrdiff_t offset);
struct frontend::StmtInfoBCE : public StmtInfoBase
{
@ -60,7 +60,7 @@ struct frontend::StmtInfoBCE : public StmtInfoBase
ptrdiff_t breaks; /* offset of last break in loop */
ptrdiff_t continues; /* offset of last continue in loop */
StmtInfoBCE(JSContext *cx) : StmtInfoBase(cx) {}
StmtInfoBCE(ExclusiveContext *cx) : StmtInfoBase(cx) {}
/*
* To reuse space, alias two of the ptrdiff_t fields for use during
@ -122,7 +122,7 @@ BytecodeEmitter::init()
}
static ptrdiff_t
EmitCheck(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t delta)
EmitCheck(ExclusiveContext *cx, BytecodeEmitter *bce, ptrdiff_t delta)
{
ptrdiff_t offset = bce->code().length();
@ -147,7 +147,7 @@ CurrentBlock(StmtInfoBCE *topStmt)
}
static void
UpdateDepth(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t target)
UpdateDepth(ExclusiveContext *cx, BytecodeEmitter *bce, ptrdiff_t target)
{
jsbytecode *pc = bce->code(target);
JSOp op = (JSOp) *pc;
@ -190,7 +190,7 @@ UpdateDepth(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t target)
}
ptrdiff_t
frontend::Emit1(JSContext *cx, BytecodeEmitter *bce, JSOp op)
frontend::Emit1(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op)
{
ptrdiff_t offset = EmitCheck(cx, bce, 1);
if (offset < 0)
@ -203,7 +203,7 @@ frontend::Emit1(JSContext *cx, BytecodeEmitter *bce, JSOp op)
}
ptrdiff_t
frontend::Emit2(JSContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1)
frontend::Emit2(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1)
{
ptrdiff_t offset = EmitCheck(cx, bce, 2);
if (offset < 0)
@ -217,7 +217,7 @@ frontend::Emit2(JSContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1)
}
ptrdiff_t
frontend::Emit3(JSContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1,
frontend::Emit3(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1,
jsbytecode op2)
{
/* These should filter through EmitVarOp. */
@ -237,7 +237,7 @@ frontend::Emit3(JSContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1,
}
ptrdiff_t
frontend::EmitN(JSContext *cx, BytecodeEmitter *bce, JSOp op, size_t extra)
frontend::EmitN(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, size_t extra)
{
ptrdiff_t length = 1 + (ptrdiff_t)extra;
ptrdiff_t offset = EmitCheck(cx, bce, length);
@ -259,7 +259,7 @@ frontend::EmitN(JSContext *cx, BytecodeEmitter *bce, JSOp op, size_t extra)
}
static ptrdiff_t
EmitJump(JSContext *cx, BytecodeEmitter *bce, JSOp op, ptrdiff_t off)
EmitJump(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, ptrdiff_t off)
{
ptrdiff_t offset = EmitCheck(cx, bce, 5);
if (offset < 0)
@ -306,10 +306,9 @@ StatementName(StmtInfoBCE *topStmt)
}
static void
ReportStatementTooLarge(JSContext *cx, StmtInfoBCE *topStmt)
ReportStatementTooLarge(TokenStream &ts, StmtInfoBCE *topStmt)
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEED_DIET,
StatementName(topStmt));
ts.reportError(JSMSG_NEED_DIET, StatementName(topStmt));
}
/*
@ -317,7 +316,7 @@ ReportStatementTooLarge(JSContext *cx, StmtInfoBCE *topStmt)
* so that we can walk back up the chain fixing up the op and jump offset.
*/
static ptrdiff_t
EmitBackPatchOp(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t *lastp)
EmitBackPatchOp(ExclusiveContext *cx, BytecodeEmitter *bce, ptrdiff_t *lastp)
{
ptrdiff_t offset, delta;
@ -330,7 +329,7 @@ EmitBackPatchOp(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t *lastp)
/* Updates line number notes, not column notes. */
static inline bool
UpdateLineNumberNotes(JSContext *cx, BytecodeEmitter *bce, uint32_t offset)
UpdateLineNumberNotes(ExclusiveContext *cx, BytecodeEmitter *bce, uint32_t offset)
{
TokenStream *ts = &bce->parser->tokenStream;
if (!ts->srcCoords.isOnThisLine(offset, bce->currentLine())) {
@ -365,7 +364,7 @@ UpdateLineNumberNotes(JSContext *cx, BytecodeEmitter *bce, uint32_t offset)
/* A function, so that we avoid macro-bloating all the other callsites. */
static bool
UpdateSourceCoordNotes(JSContext *cx, BytecodeEmitter *bce, uint32_t offset)
UpdateSourceCoordNotes(ExclusiveContext *cx, BytecodeEmitter *bce, uint32_t offset)
{
if (!UpdateLineNumberNotes(cx, bce, offset))
return false;
@ -391,7 +390,7 @@ UpdateSourceCoordNotes(JSContext *cx, BytecodeEmitter *bce, uint32_t offset)
}
static ptrdiff_t
EmitLoopHead(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
EmitLoopHead(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
{
if (nextpn) {
/*
@ -410,7 +409,7 @@ EmitLoopHead(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
}
static bool
EmitLoopEntry(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
EmitLoopEntry(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
{
if (nextpn) {
/* Update the line number, as for LOOPHEAD. */
@ -445,7 +444,7 @@ EmitLoopEntry(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
* a type set to store its result.
*/
static inline void
CheckTypeSet(JSContext *cx, BytecodeEmitter *bce, JSOp op)
CheckTypeSet(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op)
{
if (js_CodeSpec[op].format & JOF_TYPESET) {
if (bce->typesetCount < UINT16_MAX)
@ -494,7 +493,7 @@ CheckTypeSet(JSContext *cx, BytecodeEmitter *bce, JSOp op)
JS_END_MACRO
static bool
FlushPops(JSContext *cx, BytecodeEmitter *bce, int *npops)
FlushPops(ExclusiveContext *cx, BytecodeEmitter *bce, int *npops)
{
JS_ASSERT(*npops != 0);
if (NewSrcNote(cx, bce, SRC_HIDDEN) < 0)
@ -505,7 +504,7 @@ FlushPops(JSContext *cx, BytecodeEmitter *bce, int *npops)
}
static bool
PopIterator(JSContext *cx, BytecodeEmitter *bce)
PopIterator(ExclusiveContext *cx, BytecodeEmitter *bce)
{
if (NewSrcNote(cx, bce, SRC_HIDDEN) < 0)
return false;
@ -518,7 +517,7 @@ PopIterator(JSContext *cx, BytecodeEmitter *bce)
* Emit additional bytecode(s) for non-local jumps.
*/
static bool
EmitNonLocalJumpFixup(JSContext *cx, BytecodeEmitter *bce, StmtInfoBCE *toStmt)
EmitNonLocalJumpFixup(ExclusiveContext *cx, BytecodeEmitter *bce, StmtInfoBCE *toStmt)
{
/*
* The non-local jump fixup we emit will unbalance bce->stackDepth, because
@ -608,7 +607,7 @@ EmitNonLocalJumpFixup(JSContext *cx, BytecodeEmitter *bce, StmtInfoBCE *toStmt)
static const jsatomid INVALID_ATOMID = -1;
static ptrdiff_t
EmitGoto(JSContext *cx, BytecodeEmitter *bce, StmtInfoBCE *toStmt, ptrdiff_t *lastp,
EmitGoto(ExclusiveContext *cx, BytecodeEmitter *bce, StmtInfoBCE *toStmt, ptrdiff_t *lastp,
SrcNoteType noteType = SRC_NULL)
{
if (!EmitNonLocalJumpFixup(cx, bce, toStmt))
@ -623,7 +622,7 @@ EmitGoto(JSContext *cx, BytecodeEmitter *bce, StmtInfoBCE *toStmt, ptrdiff_t *la
}
static bool
BackPatch(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t last, jsbytecode *target, jsbytecode op)
BackPatch(ExclusiveContext *cx, BytecodeEmitter *bce, ptrdiff_t last, jsbytecode *target, jsbytecode op)
{
jsbytecode *pc, *stop;
ptrdiff_t delta, span;
@ -681,7 +680,7 @@ PushBlockScopeBCE(BytecodeEmitter *bce, StmtInfoBCE *stmt, StaticBlockObject &bl
// Patches |breaks| and |continues| unless the top statement info record
// represents a try-catch-finally suite. May fail if a jump offset overflows.
static bool
PopStatementBCE(JSContext *cx, BytecodeEmitter *bce)
PopStatementBCE(ExclusiveContext *cx, BytecodeEmitter *bce)
{
StmtInfoBCE *stmt = bce->topStmt;
if (!stmt->isTrying() &&
@ -695,7 +694,7 @@ PopStatementBCE(JSContext *cx, BytecodeEmitter *bce)
}
static bool
EmitIndex32(JSContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
EmitIndex32(ExclusiveContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
{
const size_t len = 1 + UINT32_INDEX_LEN;
JS_ASSERT(len == size_t(js_CodeSpec[op].length));
@ -712,7 +711,7 @@ EmitIndex32(JSContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
}
static bool
EmitIndexOp(JSContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
EmitIndexOp(ExclusiveContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
{
const size_t len = js_CodeSpec[op].length;
JS_ASSERT(len >= 1 + UINT32_INDEX_LEN);
@ -729,7 +728,7 @@ EmitIndexOp(JSContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
}
static bool
EmitAtomOp(JSContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce)
EmitAtomOp(ExclusiveContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce)
{
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
@ -746,21 +745,21 @@ EmitAtomOp(JSContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce)
}
static bool
EmitAtomOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
EmitAtomOp(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
{
JS_ASSERT(pn->pn_atom != NULL);
return EmitAtomOp(cx, pn->pn_atom, op, bce);
}
static bool
EmitObjectOp(JSContext *cx, ObjectBox *objbox, JSOp op, BytecodeEmitter *bce)
EmitObjectOp(ExclusiveContext *cx, ObjectBox *objbox, JSOp op, BytecodeEmitter *bce)
{
JS_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT);
return EmitIndex32(cx, op, bce->objectList.add(objbox), bce);
}
static bool
EmitRegExp(JSContext *cx, uint32_t index, BytecodeEmitter *bce)
EmitRegExp(ExclusiveContext *cx, uint32_t index, BytecodeEmitter *bce)
{
return EmitIndex32(cx, JSOP_REGEXP, index, bce);
}
@ -773,7 +772,7 @@ EmitRegExp(JSContext *cx, uint32_t index, BytecodeEmitter *bce)
* used as a non-asserting version of EMIT_UINT16_IMM_OP.
*/
static bool
EmitUnaliasedVarOp(JSContext *cx, JSOp op, uint16_t slot, BytecodeEmitter *bce)
EmitUnaliasedVarOp(ExclusiveContext *cx, JSOp op, uint16_t slot, BytecodeEmitter *bce)
{
JS_ASSERT(JOF_OPTYPE(op) != JOF_SCOPECOORD);
ptrdiff_t off = EmitN(cx, bce, op, sizeof(uint16_t));
@ -784,7 +783,7 @@ EmitUnaliasedVarOp(JSContext *cx, JSOp op, uint16_t slot, BytecodeEmitter *bce)
}
static bool
EmitAliasedVarOp(JSContext *cx, JSOp op, ScopeCoordinate sc, BytecodeEmitter *bce)
EmitAliasedVarOp(ExclusiveContext *cx, JSOp op, ScopeCoordinate sc, BytecodeEmitter *bce)
{
JS_ASSERT(JOF_OPTYPE(op) == JOF_SCOPECOORD);
@ -842,7 +841,7 @@ LookupAliasedName(HandleScript script, PropertyName *name, uint16_t *pslot)
}
static bool
EmitAliasedVarOp(JSContext *cx, JSOp op, ParseNode *pn, BytecodeEmitter *bce)
EmitAliasedVarOp(ExclusiveContext *cx, JSOp op, ParseNode *pn, BytecodeEmitter *bce)
{
unsigned skippedScopes = 0;
BytecodeEmitter *bceOfDef = bce;
@ -894,7 +893,7 @@ EmitAliasedVarOp(JSContext *cx, JSOp op, ParseNode *pn, BytecodeEmitter *bce)
}
static bool
EmitVarOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
EmitVarOp(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
{
JS_ASSERT(pn->isKind(PNK_FUNCTION) || pn->isKind(PNK_NAME));
JS_ASSERT(!pn->pn_cookie.isFree());
@ -935,7 +934,7 @@ GetIncDecInfo(ParseNodeKind kind, bool *post)
}
static bool
EmitVarIncDec(JSContext *cx, ParseNode *pn, BytecodeEmitter *bce)
EmitVarIncDec(ExclusiveContext *cx, ParseNode *pn, BytecodeEmitter *bce)
{
JSOp op = pn->pn_kid->getOp();
JS_ASSERT(IsArgOp(op) || IsLocalOp(op) || IsAliasedVarOp(op));
@ -1027,7 +1026,7 @@ BytecodeEmitter::isAliasedName(ParseNode *pn)
* The function returns -1 on failures.
*/
static int
AdjustBlockSlot(JSContext *cx, BytecodeEmitter *bce, int slot)
AdjustBlockSlot(ExclusiveContext *cx, BytecodeEmitter *bce, int slot)
{
JS_ASSERT((unsigned) slot < bce->maxStackDepth);
if (bce->sc->isFunctionBox()) {
@ -1041,7 +1040,7 @@ AdjustBlockSlot(JSContext *cx, BytecodeEmitter *bce, int slot)
}
static bool
EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
EmitEnterBlock(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
{
JS_ASSERT(pn->isKind(PNK_LEXICALSCOPE));
if (!EmitObjectOp(cx, pn->pn_objbox, op, bce))
@ -1070,7 +1069,7 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
JS_ASSERT(dn->isDefn());
JS_ASSERT(unsigned(dn->frameSlot() + depthPlusFixed) < JS_BIT(16));
if (!dn->pn_cookie.set(cx, dn->pn_cookie.level(),
if (!dn->pn_cookie.set(bce->parser->tokenStream, dn->pn_cookie.level(),
uint16_t(dn->frameSlot() + depthPlusFixed)))
return false;
@ -1168,7 +1167,7 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn)
default: return false;
}
pn->setOp(op);
JS_ALWAYS_TRUE(pn->pn_cookie.set(bce->sc->context, hops, slot));
JS_ALWAYS_TRUE(pn->pn_cookie.set(bce->parser->tokenStream, hops, slot));
return true;
}
hops++;
@ -1241,7 +1240,7 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn)
* op=, e.g. +=).
*/
static bool
BindNameToSlotHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
BindNameToSlotHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
JS_ASSERT(pn->isKind(PNK_NAME));
@ -1289,7 +1288,7 @@ BindNameToSlotHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (pn->isConst()) {
if (bce->sc->needStrictChecks()) {
JSAutoByteString name;
if (!js_AtomToPrintableString(cx, pn->pn_atom, &name) ||
if (!AtomToPrintableString(cx, pn->pn_atom, &name) ||
!bce->reportStrictModeError(pn, JSMSG_READ_ONLY, name.ptr()))
{
return false;
@ -1462,7 +1461,7 @@ BindNameToSlotHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
JS_ASSERT(!pn->isOp(op));
pn->setOp(op);
if (!pn->pn_cookie.set(bce->sc->context, skip, dn->pn_cookie.slot()))
if (!pn->pn_cookie.set(bce->parser->tokenStream, skip, dn->pn_cookie.slot()))
return false;
pn->pn_dflags |= PND_BOUND;
@ -1475,7 +1474,7 @@ BindNameToSlotHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* and we do not want to allow self-hosted code to use the dynamic scope.
*/
static bool
BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
BindNameToSlot(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
if (!BindNameToSlotHelper(cx, bce, pn))
return false;
@ -1501,7 +1500,7 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* pop bytecode.
*/
static bool
CheckSideEffects(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool *answer)
CheckSideEffects(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool *answer)
{
if (!pn || *answer)
return true;
@ -1729,15 +1728,20 @@ BytecodeEmitter::needsImplicitThis()
}
void
BytecodeEmitter::tellDebuggerAboutCompiledScript(JSContext *cx)
BytecodeEmitter::tellDebuggerAboutCompiledScript(ExclusiveContext *cx)
{
// Note: when parsing off thread the resulting scripts need to be handed to
// the debugger after rejoining to the main thread.
if (!cx->isJSContext())
return;
RootedFunction function(cx, script->function());
CallNewScriptHook(cx, script, function);
CallNewScriptHook(cx->asJSContext(), script, function);
if (!parent) {
GlobalObject *compileAndGoGlobal = NULL;
if (script->compileAndGo)
compileAndGoGlobal = &script->global();
Debugger::onNewScript(cx, script, compileAndGoGlobal);
Debugger::onNewScript(cx->asJSContext(), script, compileAndGoGlobal);
}
}
@ -1786,7 +1790,7 @@ BytecodeEmitter::reportStrictModeError(ParseNode *pn, unsigned errorNumber, ...)
}
static bool
EmitNameOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool callContext)
EmitNameOp(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool callContext)
{
JSOp op;
@ -1851,7 +1855,7 @@ EmitNameOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool callContext)
}
static inline bool
EmitElemOpBase(JSContext *cx, BytecodeEmitter *bce, JSOp op)
EmitElemOpBase(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op)
{
if (Emit1(cx, bce, op) < 0)
return false;
@ -1867,7 +1871,7 @@ EmitElemOpBase(JSContext *cx, BytecodeEmitter *bce, JSOp op)
}
static bool
EmitPropLHS(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
EmitPropLHS(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
{
JS_ASSERT(pn->isKind(PNK_DOT));
ParseNode *pn2 = pn->maybeExpr();
@ -1915,7 +1919,7 @@ EmitPropLHS(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
}
static bool
EmitPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
EmitPropOp(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
{
JS_ASSERT(pn->isArity(PN_NAME));
@ -1938,7 +1942,7 @@ EmitPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
}
static bool
EmitPropIncDec(JSContext *cx, ParseNode *pn, BytecodeEmitter *bce)
EmitPropIncDec(ExclusiveContext *cx, ParseNode *pn, BytecodeEmitter *bce)
{
JS_ASSERT(pn->pn_kid->getKind() == PNK_DOT);
@ -1977,7 +1981,7 @@ EmitPropIncDec(JSContext *cx, ParseNode *pn, BytecodeEmitter *bce)
}
static bool
EmitNameIncDec(JSContext *cx, ParseNode *pn, BytecodeEmitter *bce)
EmitNameIncDec(ExclusiveContext *cx, ParseNode *pn, BytecodeEmitter *bce)
{
const JSCodeSpec *cs = &js_CodeSpec[pn->pn_kid->getOp()];
@ -2014,7 +2018,7 @@ EmitNameIncDec(JSContext *cx, ParseNode *pn, BytecodeEmitter *bce)
}
static bool
EmitElemOperands(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
EmitElemOperands(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
{
ParseNode *left, *right;
@ -2061,13 +2065,13 @@ EmitElemOperands(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
}
static bool
EmitElemOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
EmitElemOp(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
{
return EmitElemOperands(cx, pn, op, bce) && EmitElemOpBase(cx, bce, op);
}
static bool
EmitElemIncDec(JSContext *cx, ParseNode *pn, BytecodeEmitter *bce)
EmitElemIncDec(ExclusiveContext *cx, ParseNode *pn, BytecodeEmitter *bce)
{
JS_ASSERT(pn->pn_kid->getKind() == PNK_ELEM);
@ -2115,7 +2119,7 @@ EmitElemIncDec(JSContext *cx, ParseNode *pn, BytecodeEmitter *bce)
}
static bool
EmitNumberOp(JSContext *cx, double dval, BytecodeEmitter *bce)
EmitNumberOp(ExclusiveContext *cx, double dval, BytecodeEmitter *bce)
{
int32_t ival;
uint32_t u;
@ -2167,7 +2171,7 @@ SetJumpOffsetAt(BytecodeEmitter *bce, ptrdiff_t off)
* into EmitTree which is recursive and uses relatively little stack space.
*/
MOZ_NEVER_INLINE static bool
EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitSwitch(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
JSOp switchOp;
bool hasDefault;
@ -2237,8 +2241,7 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
ScopedJSFreePtr<ParseNode*> table(NULL);
if (caseCount > JS_BIT(16)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TOO_MANY_CASES);
bce->parser->tokenStream.reportError(JSMSG_TOO_MANY_CASES);
return false;
}
@ -2310,7 +2313,7 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
intmap_bitlen = JS_BIT(16);
intmap = cx->pod_malloc<jsbitmap>(JS_BIT(16) >> JS_BITS_PER_WORD_LOG2);
if (!intmap) {
JS_ReportOutOfMemory(cx);
js_ReportOutOfMemory(cx);
return false;
}
}
@ -2516,7 +2519,7 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
bool
frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *body)
frontend::EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *body)
{
/*
* The decompiler has assumptions about what may occur immediately after
@ -2604,7 +2607,7 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
}
static bool
MaybeEmitVarDecl(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn,
MaybeEmitVarDecl(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn,
jsatomid *result)
{
jsatomid atomIndex;
@ -2650,10 +2653,10 @@ enum VarEmitOption
#if JS_HAS_DESTRUCTURING
typedef bool
(*DestructuringDeclEmitter)(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn);
(*DestructuringDeclEmitter)(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn);
static bool
EmitDestructuringDecl(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn)
EmitDestructuringDecl(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn)
{
JS_ASSERT(pn->isKind(PNK_NAME));
if (!BindNameToSlot(cx, bce, pn))
@ -2664,7 +2667,7 @@ EmitDestructuringDecl(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseN
}
static bool
EmitDestructuringDecls(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn)
EmitDestructuringDecls(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn)
{
ParseNode *pn2, *pn3;
DestructuringDeclEmitter emitter;
@ -2692,7 +2695,7 @@ EmitDestructuringDecls(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, Parse
}
static bool
EmitDestructuringOpsHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn,
EmitDestructuringOpsHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
VarEmitOption emitOption);
/*
@ -2708,7 +2711,7 @@ EmitDestructuringOpsHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn,
* lhs expression. (Same post-condition as EmitDestructuringOpsHelper)
*/
static bool
EmitDestructuringLHS(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption emitOption)
EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption emitOption)
{
JS_ASSERT(emitOption != DefineVars);
@ -2825,7 +2828,7 @@ EmitDestructuringLHS(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmit
* lhs expression. (Same post-condition as EmitDestructuringLHS)
*/
static bool
EmitDestructuringOpsHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn,
EmitDestructuringOpsHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
VarEmitOption emitOption)
{
JS_ASSERT(emitOption != DefineVars);
@ -2942,7 +2945,7 @@ EmitDestructuringOpsHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn,
}
static bool
EmitDestructuringOps(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool isLet = false)
EmitDestructuringOps(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool isLet = false)
{
/*
* Call our recursive helper to emit the destructuring assignments and
@ -2953,7 +2956,7 @@ EmitDestructuringOps(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool is
}
static bool
EmitGroupAssignment(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp,
EmitGroupAssignment(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp,
ParseNode *lhs, ParseNode *rhs)
{
unsigned depth, limit, i, nslots;
@ -3007,7 +3010,7 @@ enum GroupOption { GroupIsDecl, GroupIsNotDecl };
* we set *pop to JSOP_NOP so callers can veto emitting pn followed by a pop.
*/
static bool
MaybeEmitGroupAssignment(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn,
MaybeEmitGroupAssignment(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn,
GroupOption groupOption, JSOp *pop)
{
JS_ASSERT(pn->isKind(PNK_ASSIGN));
@ -3040,7 +3043,7 @@ MaybeEmitGroupAssignment(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, Par
* 1:1 correspondence and lhs elements are simple names.
*/
static bool
MaybeEmitLetGroupDecl(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp *pop)
MaybeEmitLetGroupDecl(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp *pop)
{
JS_ASSERT(pn->isKind(PNK_ASSIGN));
JS_ASSERT(pn->isOp(JSOP_NOP));
@ -3071,7 +3074,7 @@ MaybeEmitLetGroupDecl(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp *
#endif /* JS_HAS_DESTRUCTURING */
static bool
EmitVariables(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption emitOption,
EmitVariables(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption emitOption,
bool isLet = false)
{
JS_ASSERT(pn->isArity(PN_LIST));
@ -3260,7 +3263,7 @@ EmitVariables(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption
}
static bool
EmitAssignment(JSContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp op, ParseNode *rhs)
EmitAssignment(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp op, ParseNode *rhs)
{
/*
* Check left operand type and generate specialized code for it.
@ -3465,7 +3468,7 @@ EmitAssignment(JSContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp op, Par
}
static bool
EmitNewInit(JSContext *cx, BytecodeEmitter *bce, JSProtoKey key, ParseNode *pn)
EmitNewInit(ExclusiveContext *cx, BytecodeEmitter *bce, JSProtoKey key, ParseNode *pn)
{
const size_t len = 1 + UINT32_INDEX_LEN;
ptrdiff_t offset = EmitCheck(cx, bce, len);
@ -3484,7 +3487,7 @@ EmitNewInit(JSContext *cx, BytecodeEmitter *bce, JSProtoKey key, ParseNode *pn)
}
bool
ParseNode::getConstantValue(JSContext *cx, bool strictChecks, MutableHandleValue vp)
ParseNode::getConstantValue(ExclusiveContext *cx, bool strictChecks, MutableHandleValue vp)
{
switch (getKind()) {
case PNK_NUMBER:
@ -3587,7 +3590,7 @@ ParseNode::getConstantValue(JSContext *cx, bool strictChecks, MutableHandleValue
}
static bool
EmitSingletonInitialiser(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitSingletonInitialiser(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
RootedValue value(cx);
if (!pn->getConstantValue(cx, bce->sc->needStrictChecks(), &value))
@ -3614,7 +3617,7 @@ class EmitLevelManager
};
static bool
EmitCatch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitCatch(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
ptrdiff_t guardJump;
@ -3698,7 +3701,7 @@ EmitCatch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* the comment on EmitSwitch.
*/
MOZ_NEVER_INLINE static bool
EmitTry(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitTry(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
StmtInfoBCE stmtInfo(cx);
ptrdiff_t catchJump = -1;
@ -3919,7 +3922,7 @@ EmitTry(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitIf(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitIf(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
StmtInfoBCE stmtInfo(cx);
@ -4033,7 +4036,7 @@ EmitIf(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* the comment on EmitSwitch.
*/
MOZ_NEVER_INLINE static bool
EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
EmitLet(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
{
JS_ASSERT(pnLet->isArity(PN_BINARY));
ParseNode *varList = pnLet->pn_left;
@ -4081,7 +4084,7 @@ EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
* the comment on EmitSwitch.
*/
MOZ_NEVER_INLINE static bool
EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitLexicalScope(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
JS_ASSERT(pn->isKind(PNK_LEXICALSCOPE));
JS_ASSERT(pn->getOp() == JSOP_LEAVEBLOCK);
@ -4104,7 +4107,7 @@ EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitWith(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitWith(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
StmtInfoBCE stmtInfo(cx);
if (!EmitTree(cx, bce, pn->pn_left))
@ -4121,7 +4124,7 @@ EmitWith(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
EmitForIn(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
StmtInfoBCE stmtInfo(cx);
PushStatementBCE(bce, &stmtInfo, STMT_FOR_IN_LOOP, top);
@ -4286,7 +4289,7 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
}
static bool
EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
EmitNormalFor(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
StmtInfoBCE stmtInfo(cx);
PushStatementBCE(bce, &stmtInfo, STMT_FOR_LOOP, top);
@ -4437,7 +4440,7 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
}
static inline bool
EmitFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
EmitFor(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
JS_ASSERT(pn->pn_left->isKind(PNK_FORIN) || pn->pn_left->isKind(PNK_FORHEAD));
return pn->pn_left->isKind(PNK_FORIN)
@ -4446,7 +4449,7 @@ EmitFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
}
static JS_NEVER_INLINE bool
EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitFunc(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
FunctionBox *funbox = pn->pn_funbox;
RootedFunction fun(cx, funbox->function());
@ -4477,7 +4480,8 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* make a deep clone of its contents.
*/
bool singleton =
cx->typeInferenceEnabled() &&
cx->isJSContext() &&
cx->asJSContext()->typeInferenceEnabled() &&
bce->script->compileAndGo &&
(bce->checkSingletonContext() ||
(!bce->isInLoop() &&
@ -4502,17 +4506,23 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
// Inherit most things (principals, version, etc) from the parent.
Rooted<JSScript*> parent(cx, bce->script);
CompileOptions options(cx);
CompileOptions options(bce->parser->options());
options.setPrincipals(parent->principals())
.setOriginPrincipals(parent->originPrincipals)
.setCompileAndGo(parent->compileAndGo)
.setSelfHostingMode(parent->selfHosted)
.setNoScriptRval(false)
.setForEval(false)
.setVersion(parent->getVersion());
bool generateBytecode = true;
#ifdef JS_ION
if (funbox->useAsm) {
if (!cx->isJSContext()) {
bce->parser->tokenStream.reportError(JSMSG_SYNTAX_ERROR);
return false;
}
RootedFunction moduleFun(cx);
// In a function like this:
@ -4523,7 +4533,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
// one past the final '}'. We need to exclude that final '}',
// so we use |funbox->bufEnd - 1| below.
//
if (!CompileAsmJS(cx, *bce->tokenStream(), pn, options,
if (!CompileAsmJS(cx->asJSContext(), *bce->tokenStream(), pn, options,
bce->script->scriptSource(), funbox->asmStart, funbox->bufEnd - 1,
&moduleFun))
return false;
@ -4612,7 +4622,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitDo(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitDo(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
/* Emit an annotated nop so we know to decompile a 'do' keyword. */
ptrdiff_t noteIndex = NewSrcNote(cx, bce, SRC_WHILE);
@ -4673,7 +4683,7 @@ EmitDo(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitWhile(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
EmitWhile(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
/*
* Minimize bytecodes issued for one or more iterations by jumping to
@ -4726,7 +4736,7 @@ EmitWhile(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
}
static bool
EmitBreak(JSContext *cx, BytecodeEmitter *bce, PropertyName *label)
EmitBreak(ExclusiveContext *cx, BytecodeEmitter *bce, PropertyName *label)
{
StmtInfoBCE *stmt = bce->topStmt;
SrcNoteType noteType;
@ -4744,7 +4754,7 @@ EmitBreak(JSContext *cx, BytecodeEmitter *bce, PropertyName *label)
}
static bool
EmitContinue(JSContext *cx, BytecodeEmitter *bce, PropertyName *label)
EmitContinue(ExclusiveContext *cx, BytecodeEmitter *bce, PropertyName *label)
{
StmtInfoBCE *stmt = bce->topStmt;
if (label) {
@ -4765,7 +4775,7 @@ EmitContinue(JSContext *cx, BytecodeEmitter *bce, PropertyName *label)
}
static bool
EmitReturn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitReturn(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
if (!UpdateSourceCoordNotes(cx, bce, pn->pn_pos.begin))
return false;
@ -4807,7 +4817,7 @@ EmitReturn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitStatementList(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
EmitStatementList(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
JS_ASSERT(pn->isArity(PN_LIST));
@ -4828,7 +4838,7 @@ EmitStatementList(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t
}
static bool
EmitStatement(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitStatement(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
JS_ASSERT(pn->isKind(PNK_SEMI));
@ -4904,7 +4914,7 @@ EmitStatement(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitDelete(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitDelete(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
/*
* Under ECMA 3, deleting a non-reference returns true -- but alas we
@ -4961,7 +4971,7 @@ EmitDelete(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
bool callop = pn->isKind(PNK_CALL);
@ -4983,8 +4993,9 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
uint32_t argc = pn->pn_count - 1;
if (argc >= ARGC_LIMIT) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
callop ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
bce->parser->tokenStream.reportError(callop
? JSMSG_TOO_MANY_FUN_ARGS
: JSMSG_TOO_MANY_CON_ARGS);
return false;
}
@ -5111,7 +5122,7 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitLogical(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitLogical(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
/*
* JSOP_OR converts the operand on the stack to boolean, leaves the original
@ -5187,7 +5198,7 @@ EmitLogical(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* the comment on EmitSwitch.
*/
MOZ_NEVER_INLINE static bool
EmitIncOrDec(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitIncOrDec(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
/* Emit lvalue-specialized code for ++/-- operators. */
ParseNode *pn2 = pn->pn_kid;
@ -5266,7 +5277,7 @@ EmitIncOrDec(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* the comment on EmitSwitch.
*/
MOZ_NEVER_INLINE static bool
EmitLabeledStatement(JSContext *cx, BytecodeEmitter *bce, const LabeledStatement *pn)
EmitLabeledStatement(ExclusiveContext *cx, BytecodeEmitter *bce, const LabeledStatement *pn)
{
/*
* Emit a JSOP_LABEL instruction. The argument is the offset to the statement
@ -5295,7 +5306,7 @@ EmitLabeledStatement(JSContext *cx, BytecodeEmitter *bce, const LabeledStatement
}
static bool
EmitSyntheticStatements(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
EmitSyntheticStatements(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
JS_ASSERT(pn->isArity(PN_LIST));
StmtInfoBCE stmtInfo(cx);
@ -5311,7 +5322,7 @@ EmitSyntheticStatements(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrd
}
static bool
EmitConditionalExpression(JSContext *cx, BytecodeEmitter *bce, ConditionalExpression &conditional)
EmitConditionalExpression(ExclusiveContext *cx, BytecodeEmitter *bce, ConditionalExpression &conditional)
{
/* Emit the condition, then branch if false to the else part. */
if (!EmitTree(cx, bce, &conditional.condition()))
@ -5352,7 +5363,7 @@ EmitConditionalExpression(JSContext *cx, BytecodeEmitter *bce, ConditionalExpres
* the comment on EmitSwitch.
*/
MOZ_NEVER_INLINE static bool
EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
#if JS_HAS_DESTRUCTURING_SHORTHAND
if (pn->pn_xflags & PNX_DESTRUCT) {
@ -5470,7 +5481,7 @@ EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitArray(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitArray(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
/*
* Emit code for [a, b, c] that is equivalent to constructing a new
@ -5557,7 +5568,7 @@ EmitArray(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitUnary(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitUnary(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
if (!UpdateSourceCoordNotes(cx, bce, pn->pn_pos.begin))
return false;
@ -5578,7 +5589,7 @@ EmitUnary(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static bool
EmitDefaults(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
EmitDefaults(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
JS_ASSERT(pn->isKind(PNK_ARGSBODY));
@ -5613,7 +5624,7 @@ EmitDefaults(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
bool
frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
JS_CHECK_RECURSION(cx, return false);
@ -6027,7 +6038,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
static int
AllocSrcNote(JSContext *cx, SrcNotesVector &notes)
AllocSrcNote(ExclusiveContext *cx, SrcNotesVector &notes)
{
// Start it off moderately large to avoid repeated resizings early on.
if (notes.capacity() == 0 && !notes.reserve(1024))
@ -6042,7 +6053,7 @@ AllocSrcNote(JSContext *cx, SrcNotesVector &notes)
}
int
frontend::NewSrcNote(JSContext *cx, BytecodeEmitter *bce, SrcNoteType type)
frontend::NewSrcNote(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type)
{
SrcNotesVector &notes = bce->notes();
int index;
@ -6083,7 +6094,7 @@ frontend::NewSrcNote(JSContext *cx, BytecodeEmitter *bce, SrcNoteType type)
}
int
frontend::NewSrcNote2(JSContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset)
frontend::NewSrcNote2(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset)
{
int index;
@ -6096,7 +6107,7 @@ frontend::NewSrcNote2(JSContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptr
}
int
frontend::NewSrcNote3(JSContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset1,
frontend::NewSrcNote3(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset1,
ptrdiff_t offset2)
{
int index;
@ -6112,7 +6123,7 @@ frontend::NewSrcNote3(JSContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptr
}
bool
frontend::AddToSrcNoteDelta(JSContext *cx, BytecodeEmitter *bce, jssrcnote *sn, ptrdiff_t delta)
frontend::AddToSrcNoteDelta(ExclusiveContext *cx, BytecodeEmitter *bce, jssrcnote *sn, ptrdiff_t delta)
{
/*
* Called only from FinishTakingSrcNotes to add to main script note
@ -6136,11 +6147,11 @@ frontend::AddToSrcNoteDelta(JSContext *cx, BytecodeEmitter *bce, jssrcnote *sn,
}
static bool
SetSrcNoteOffset(JSContext *cx, BytecodeEmitter *bce, unsigned index, unsigned which,
SetSrcNoteOffset(ExclusiveContext *cx, BytecodeEmitter *bce, unsigned index, unsigned which,
ptrdiff_t offset)
{
if (size_t(offset) > SN_MAX_OFFSET) {
ReportStatementTooLarge(cx, bce->topStmt);
ReportStatementTooLarge(bce->parser->tokenStream, bce->topStmt);
return false;
}
@ -6218,7 +6229,7 @@ DumpSrcNoteSizeHist()
* CORRESPONDING CHANGES!
*/
bool
frontend::FinishTakingSrcNotes(JSContext *cx, BytecodeEmitter *bce, jssrcnote *notes)
frontend::FinishTakingSrcNotes(ExclusiveContext *cx, BytecodeEmitter *bce, jssrcnote *notes)
{
JS_ASSERT(bce->current == &bce->main);

View File

@ -26,7 +26,7 @@ namespace frontend {
struct CGTryNoteList {
Vector<JSTryNote> list;
CGTryNoteList(JSContext *cx) : list(cx) {}
CGTryNoteList(ExclusiveContext *cx) : list(cx) {}
bool append(JSTryNoteKind kind, unsigned stackDepth, size_t start, size_t end);
size_t length() const { return list.length(); }
@ -47,7 +47,7 @@ struct CGObjectList {
class CGConstList {
Vector<Value> list;
public:
CGConstList(JSContext *cx) : list(cx) {}
CGConstList(ExclusiveContext *cx) : list(cx) {}
bool append(Value v) { JS_ASSERT_IF(v.isString(), v.toString()->isAtom()); return list.append(v); }
size_t length() const { return list.length(); }
void finish(ConstArray *array);
@ -78,7 +78,7 @@ struct BytecodeEmitter
uint32_t lastColumn; /* zero-based column index on currentLine of
last SRC_COLSPAN-annotated opcode */
EmitSection(JSContext *cx, uint32_t lineNum)
EmitSection(ExclusiveContext *cx, uint32_t lineNum)
: code(cx), notes(cx), lastNoteOffset(0), currentLine(lineNum), lastColumn(0)
{}
};
@ -180,7 +180,7 @@ struct BytecodeEmitter
bool needsImplicitThis();
void tellDebuggerAboutCompiledScript(JSContext *cx);
void tellDebuggerAboutCompiledScript(ExclusiveContext *cx);
inline TokenStream *tokenStream();
@ -207,37 +207,37 @@ struct BytecodeEmitter
* Emit one bytecode.
*/
ptrdiff_t
Emit1(JSContext *cx, BytecodeEmitter *bce, JSOp op);
Emit1(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op);
/*
* Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1).
*/
ptrdiff_t
Emit2(JSContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1);
Emit2(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1);
/*
* Emit three bytecodes, an opcode with two bytes of immediate operands.
*/
ptrdiff_t
Emit3(JSContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1, jsbytecode op2);
Emit3(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1, jsbytecode op2);
/*
* Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
*/
ptrdiff_t
EmitN(JSContext *cx, BytecodeEmitter *bce, JSOp op, size_t extra);
EmitN(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, size_t extra);
/*
* Emit code into bce for the tree rooted at pn.
*/
bool
EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn);
EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn);
/*
* Emit function code using bce for the tree rooted at body.
*/
bool
EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *body);
EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *body);
/*
* Append a new source note of the given type (and therefore size) to bce's
@ -246,21 +246,21 @@ EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *body);
* memory.
*/
int
NewSrcNote(JSContext *cx, BytecodeEmitter *bce, SrcNoteType type);
NewSrcNote(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type);
int
NewSrcNote2(JSContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset);
NewSrcNote2(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset);
int
NewSrcNote3(JSContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset1,
NewSrcNote3(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset1,
ptrdiff_t offset2);
/* NB: this function can add at most one extra extended delta note. */
bool
AddToSrcNoteDelta(JSContext *cx, BytecodeEmitter *bce, jssrcnote *sn, ptrdiff_t delta);
AddToSrcNoteDelta(ExclusiveContext *cx, BytecodeEmitter *bce, jssrcnote *sn, ptrdiff_t delta);
bool
FinishTakingSrcNotes(JSContext *cx, BytecodeEmitter *bce, jssrcnote *notes);
FinishTakingSrcNotes(ExclusiveContext *cx, BytecodeEmitter *bce, jssrcnote *notes);
/*
* Finish taking source notes in cx's notePool, copying final notes to the new

View File

@ -15,6 +15,8 @@
#include "frontend/Parser.h"
#include "vm/NumericConversions.h"
#include "jscntxtinlines.h"
using namespace js;
using namespace js::frontend;
@ -67,7 +69,7 @@ ContainsVarOrConst(ParseNode *pn)
* XXX handles only strings and numbers for now
*/
static bool
FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
FoldType(ExclusiveContext *cx, ParseNode *pn, ParseNodeKind kind)
{
if (!pn->isKind(kind)) {
switch (kind) {
@ -107,7 +109,7 @@ FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
* a successful call to this function.
*/
static bool
FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
FoldBinaryNumeric(ExclusiveContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
ParseNode *pn)
{
double d, d2;
@ -244,8 +246,9 @@ condIf(const ParseNode *pn, ParseNodeKind kind)
}
static bool
Fold(JSContext *cx, ParseNode **pnp, FullParseHandler &handler, bool inGenexpLambda,
SyntacticContext sc)
Fold(ExclusiveContext *cx, ParseNode **pnp,
FullParseHandler &handler, const CompileOptions &options,
bool inGenexpLambda, SyntacticContext sc)
{
ParseNode *pn = *pnp;
ParseNode *pn1 = NULL, *pn2 = NULL, *pn3 = NULL;
@ -256,18 +259,18 @@ Fold(JSContext *cx, ParseNode **pnp, FullParseHandler &handler, bool inGenexpLam
switch (pn->getArity()) {
case PN_CODE:
if (pn->isKind(PNK_FUNCTION) &&
pn->pn_funbox->useAsmOrInsideUseAsm() && cx->hasOption(JSOPTION_ASMJS))
pn->pn_funbox->useAsmOrInsideUseAsm() && options.asmJSOption)
{
return true;
}
if (pn->getKind() == PNK_MODULE) {
if (!Fold(cx, &pn->pn_body, handler, false, SyntacticContext::Other))
if (!Fold(cx, &pn->pn_body, handler, options, false, SyntacticContext::Other))
return false;
} else {
// Note: pn_body is NULL for functions which are being lazily parsed.
JS_ASSERT(pn->getKind() == PNK_FUNCTION);
if (pn->pn_body) {
if (!Fold(cx, &pn->pn_body, handler, pn->pn_funbox->inGenexpLambda,
if (!Fold(cx, &pn->pn_body, handler, options, pn->pn_funbox->inGenexpLambda,
SyntacticContext::Other))
return false;
}
@ -287,7 +290,7 @@ Fold(JSContext *cx, ParseNode **pnp, FullParseHandler &handler, bool inGenexpLam
listp = &(*listp)->pn_next;
for (; *listp; listp = &(*listp)->pn_next) {
if (!Fold(cx, listp, handler, inGenexpLambda, kidsc))
if (!Fold(cx, listp, handler, options, inGenexpLambda, kidsc))
return false;
}
@ -303,13 +306,13 @@ Fold(JSContext *cx, ParseNode **pnp, FullParseHandler &handler, bool inGenexpLam
case PN_TERNARY:
/* Any kid may be null (e.g. for (;;)). */
if (pn->pn_kid1) {
if (!Fold(cx, &pn->pn_kid1, handler, inGenexpLambda, condIf(pn, PNK_IF)))
if (!Fold(cx, &pn->pn_kid1, handler, options, inGenexpLambda, condIf(pn, PNK_IF)))
return false;
}
pn1 = pn->pn_kid1;
if (pn->pn_kid2) {
if (!Fold(cx, &pn->pn_kid2, handler, inGenexpLambda, condIf(pn, PNK_FORHEAD)))
if (!Fold(cx, &pn->pn_kid2, handler, options, inGenexpLambda, condIf(pn, PNK_FORHEAD)))
return false;
if (pn->isKind(PNK_FORHEAD) && pn->pn_kid2->isKind(PNK_TRUE)) {
handler.freeTree(pn->pn_kid2);
@ -319,7 +322,7 @@ Fold(JSContext *cx, ParseNode **pnp, FullParseHandler &handler, bool inGenexpLam
pn2 = pn->pn_kid2;
if (pn->pn_kid3) {
if (!Fold(cx, &pn->pn_kid3, handler, inGenexpLambda, SyntacticContext::Other))
if (!Fold(cx, &pn->pn_kid3, handler, options, inGenexpLambda, SyntacticContext::Other))
return false;
}
pn3 = pn->pn_kid3;
@ -331,17 +334,17 @@ Fold(JSContext *cx, ParseNode **pnp, FullParseHandler &handler, bool inGenexpLam
SyntacticContext kidsc = SyntacticContext::Other;
if (sc == SyntacticContext::Condition)
kidsc = sc;
if (!Fold(cx, &pn->pn_left, handler, inGenexpLambda, kidsc))
if (!Fold(cx, &pn->pn_left, handler, options, inGenexpLambda, kidsc))
return false;
if (!Fold(cx, &pn->pn_right, handler, inGenexpLambda, kidsc))
if (!Fold(cx, &pn->pn_right, handler, options, inGenexpLambda, kidsc))
return false;
} else {
/* First kid may be null (for default case in switch). */
if (pn->pn_left) {
if (!Fold(cx, &pn->pn_left, handler, inGenexpLambda, condIf(pn, PNK_WHILE)))
if (!Fold(cx, &pn->pn_left, handler, options, inGenexpLambda, condIf(pn, PNK_WHILE)))
return false;
}
if (!Fold(cx, &pn->pn_right, handler, inGenexpLambda, condIf(pn, PNK_DOWHILE)))
if (!Fold(cx, &pn->pn_right, handler, options, inGenexpLambda, condIf(pn, PNK_DOWHILE)))
return false;
}
pn1 = pn->pn_left;
@ -368,7 +371,7 @@ Fold(JSContext *cx, ParseNode **pnp, FullParseHandler &handler, bool inGenexpLam
: pn->isKind(PNK_DELETE)
? SyntacticContext::Delete
: SyntacticContext::Other;
if (!Fold(cx, &pn->pn_kid, handler, inGenexpLambda, kidsc))
if (!Fold(cx, &pn->pn_kid, handler, options, inGenexpLambda, kidsc))
return false;
}
pn1 = pn->pn_kid;
@ -385,7 +388,7 @@ Fold(JSContext *cx, ParseNode **pnp, FullParseHandler &handler, bool inGenexpLam
ParseNode **lhsp = &pn->pn_expr;
while (*lhsp && (*lhsp)->isArity(PN_NAME) && !(*lhsp)->isUsed())
lhsp = &(*lhsp)->pn_expr;
if (*lhsp && !Fold(cx, lhsp, handler, inGenexpLambda, SyntacticContext::Other))
if (*lhsp && !Fold(cx, lhsp, handler, options, inGenexpLambda, SyntacticContext::Other))
return false;
pn1 = *lhsp;
}
@ -804,15 +807,14 @@ Fold(JSContext *cx, ParseNode **pnp, FullParseHandler &handler, bool inGenexpLam
}
bool
frontend::FoldConstants(JSContext *cx, ParseNode **pnp, Parser<FullParseHandler> *parser)
frontend::FoldConstants(ExclusiveContext *cx, ParseNode **pnp, Parser<FullParseHandler> *parser)
{
// Don't fold constants if the code has requested "use asm" as
// constant-folding will misrepresent the source text for the purpose
// of type checking. (Also guard against entering a function containing
// "use asm", see PN_FUNC case below.)
if (parser->pc->useAsmOrInsideUseAsm() && cx->hasOption(JSOPTION_ASMJS))
if (parser->pc->useAsmOrInsideUseAsm() && parser->options().asmJSOption)
return true;
return Fold(cx, pnp, parser->handler, false, SyntacticContext::Other);
return Fold(cx, pnp, parser->handler, parser->options(), false, SyntacticContext::Other);
}

View File

@ -28,10 +28,11 @@ namespace frontend {
// if (!FoldConstants(cx, &pn, parser))
// return false;
bool
FoldConstants(JSContext *cx, ParseNode **pnp, Parser<FullParseHandler> *parser);
FoldConstants(ExclusiveContext *cx, ParseNode **pnp, Parser<FullParseHandler> *parser);
inline bool
FoldConstants(JSContext *cx, SyntaxParseHandler::Node *pnp, Parser<SyntaxParseHandler> *parser)
FoldConstants(ExclusiveContext *cx, SyntaxParseHandler::Node *pnp,
Parser<SyntaxParseHandler> *parser)
{
return true;
}

View File

@ -69,9 +69,10 @@ class FullParseHandler
typedef ParseNode *Node;
typedef Definition *DefinitionNode;
FullParseHandler(JSContext *cx, TokenStream &tokenStream, bool foldConstants,
FullParseHandler(ExclusiveContext *cx, LifoAlloc &alloc,
TokenStream &tokenStream, bool foldConstants,
Parser<SyntaxParseHandler> *syntaxParser, LazyScript *lazyOuterFunction)
: allocator(cx),
: allocator(cx, alloc),
tokenStream(tokenStream),
foldConstants(foldConstants),
lazyOuterFunction_(lazyOuterFunction),

View File

@ -16,21 +16,21 @@ namespace frontend {
template <class Map>
inline bool
AtomThingMapPtr<Map>::ensureMap(JSContext *cx)
AtomThingMapPtr<Map>::ensureMap(ExclusiveContext *cx)
{
if (map_)
return true;
map_ = cx->runtime()->parseMapPool.acquire<Map>();
map_ = cx->parseMapPool().acquire<Map>();
return !!map_;
}
template <class Map>
inline void
AtomThingMapPtr<Map>::releaseMap(JSContext *cx)
AtomThingMapPtr<Map>::releaseMap(ExclusiveContext *cx)
{
if (!map_)
return;
cx->runtime()->parseMapPool.release(map_);
cx->parseMapPool().release(map_);
map_ = NULL;
}
@ -38,7 +38,7 @@ template <typename ParseHandler>
inline bool
AtomDecls<ParseHandler>::init()
{
map = cx->runtime()->parseMapPool.acquire<AtomDefnListMap>();
map = cx->parseMapPool().acquire<AtomDefnListMap>();
return map;
}
@ -47,7 +47,7 @@ inline
AtomDecls<ParseHandler>::~AtomDecls()
{
if (map)
cx->runtime()->parseMapPool.release(map);
cx->parseMapPool().release(map);
}
} /* namespace frontend */

View File

@ -58,9 +58,9 @@ ParseMapPool::allocateFresh()
}
DefinitionList::Node *
DefinitionList::allocNode(JSContext *cx, uintptr_t head, Node *tail)
DefinitionList::allocNode(ExclusiveContext *cx, LifoAlloc &alloc, uintptr_t head, Node *tail)
{
Node *result = cx->tempLifoAlloc().new_<Node>(head, tail);
Node *result = alloc.new_<Node>(head, tail);
if (!result)
js_ReportOutOfMemory(cx);
return result;
@ -105,11 +105,11 @@ AtomDecls<ParseHandler>::addShadow(JSAtom *atom, typename ParseHandler::Definiti
if (!p)
return map->add(p, atom, DefinitionList(ParseHandler::definitionToBits(defn)));
return p.value().pushFront<ParseHandler>(cx, defn);
return p.value().pushFront<ParseHandler>(cx, alloc, defn);
}
void
frontend::InitAtomMap(JSContext *cx, frontend::AtomIndexMap *indices, HeapPtrAtom *atoms)
frontend::InitAtomMap(frontend::AtomIndexMap *indices, HeapPtrAtom *atoms)
{
if (indices->isMap()) {
typedef AtomIndexMap::WordMap WordMap;

View File

@ -30,7 +30,7 @@ typedef InlineMap<JSAtom *, DefinitionList, 24> AtomDefnListMap;
* the list and map->vector must point to pre-allocated memory.
*/
void
InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtr<JSAtom> *atoms);
InitAtomMap(AtomIndexMap *indices, HeapPtr<JSAtom> *atoms);
/*
* A pool that permits the reuse of the backing storage for the defn, index, or
@ -127,8 +127,8 @@ struct AtomThingMapPtr
void init() { clearMap(); }
bool ensureMap(JSContext *cx);
void releaseMap(JSContext *cx);
bool ensureMap(ExclusiveContext *cx);
void releaseMap(ExclusiveContext *cx);
bool hasMap() const { return map_; }
Map *getMap() { return map_; }
@ -149,10 +149,10 @@ typedef AtomThingMapPtr<AtomIndexMap> AtomIndexMapPtr;
template <typename AtomThingMapPtrT>
class OwnedAtomThingMapPtr : public AtomThingMapPtrT
{
JSContext *cx;
ExclusiveContext *cx;
public:
explicit OwnedAtomThingMapPtr(JSContext *cx) : cx(cx) {
explicit OwnedAtomThingMapPtr(ExclusiveContext *cx) : cx(cx) {
AtomThingMapPtrT::init();
}
@ -244,8 +244,8 @@ class DefinitionList
}
static Node *
allocNode(JSContext *cx, uintptr_t bits, Node *tail);
allocNode(ExclusiveContext *cx, LifoAlloc &alloc, uintptr_t bits, Node *tail);
public:
class Range
{
@ -336,17 +336,18 @@ class DefinitionList
* Return true on success. On OOM, report on cx and return false.
*/
template <typename ParseHandler>
bool pushFront(JSContext *cx, typename ParseHandler::DefinitionNode defn) {
bool pushFront(ExclusiveContext *cx, LifoAlloc &alloc,
typename ParseHandler::DefinitionNode defn) {
Node *tail;
if (isMultiple()) {
tail = firstNode();
} else {
tail = allocNode(cx, u.bits, NULL);
tail = allocNode(cx, alloc, u.bits, NULL);
if (!tail)
return false;
}
Node *node = allocNode(cx, ParseHandler::definitionToBits(defn), tail);
Node *node = allocNode(cx, alloc, ParseHandler::definitionToBits(defn), tail);
if (!node)
return false;
*this = DefinitionList(node);
@ -404,14 +405,15 @@ class AtomDecls
/* AtomDeclsIter needs to get at the DefnListMap directly. */
friend class AtomDeclsIter;
JSContext *cx;
ExclusiveContext *cx;
LifoAlloc &alloc;
AtomDefnListMap *map;
AtomDecls(const AtomDecls &other) MOZ_DELETE;
void operator=(const AtomDecls &other) MOZ_DELETE;
public:
explicit AtomDecls(JSContext *cx) : cx(cx), map(NULL) {}
explicit AtomDecls(ExclusiveContext *cx, LifoAlloc &alloc) : cx(cx), alloc(alloc), map(NULL) {}
~AtomDecls();

View File

@ -8,6 +8,8 @@
#include "frontend/ParseNode.h"
#include "frontend/Parser.h"
#include "jscntxtinlines.h"
using namespace js;
using namespace js::frontend;
@ -240,7 +242,7 @@ ParseNodeAllocator::allocNode()
return pn;
}
void *p = cx->tempLifoAlloc().alloc(sizeof (ParseNode));
void *p = alloc.alloc(sizeof (ParseNode));
if (!p)
js_ReportOutOfMemory(cx);
return p;

View File

@ -51,15 +51,13 @@ class UpvarCookie
uint16_t slot() const { JS_ASSERT(!isFree()); return slot_; }
// This fails and issues an error message if newLevel is too large.
bool set(JSContext *cx, unsigned newLevel, uint16_t newSlot) {
bool set(TokenStream &ts, unsigned newLevel, uint16_t newSlot) {
// This is an unsigned-to-uint16_t conversion, test for too-high
// values. In practice, recursion in Parser and/or BytecodeEmitter
// will blow the stack if we nest functions more than a few hundred
// deep, so this will never trigger. Oh well.
if (newLevel >= FREE_LEVEL) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_DEEP, js_function_str);
return false;
}
if (newLevel >= FREE_LEVEL)
return ts.reportError(JSMSG_TOO_DEEP);
level_ = newLevel;
slot_ = newSlot;
return true;
@ -803,7 +801,7 @@ class ParseNode
#endif
;
bool getConstantValue(JSContext *cx, bool strictChecks, MutableHandleValue vp);
bool getConstantValue(ExclusiveContext *cx, bool strictChecks, MutableHandleValue vp);
inline bool isConstant();
template <class NodeType>
@ -1357,7 +1355,9 @@ struct Definition : public ParseNode
class ParseNodeAllocator
{
public:
explicit ParseNodeAllocator(JSContext *cx) : cx(cx), freelist(NULL) {}
explicit ParseNodeAllocator(ExclusiveContext *cx, LifoAlloc &alloc)
: cx(cx), alloc(alloc), freelist(NULL)
{}
void *allocNode();
void freeNode(ParseNode *pn);
@ -1365,7 +1365,8 @@ class ParseNodeAllocator
void prepareNodeForMutation(ParseNode *pn);
private:
JSContext *cx;
ExclusiveContext *cx;
LifoAlloc &alloc;
ParseNode *freelist;
};

View File

@ -77,7 +77,10 @@ bool
GenerateBlockId(ParseContext<ParseHandler> *pc, uint32_t &blockid)
{
if (pc->blockidGen == JS_BIT(20)) {
JS_ReportErrorNumber(pc->sc->context, js_GetErrorMessage, NULL, JSMSG_NEED_DIET, "program");
if (!pc->sc->context->isJSContext())
return false;
JS_ReportErrorNumber(pc->sc->context->asJSContext(),
js_GetErrorMessage, NULL, JSMSG_NEED_DIET, "program");
return false;
}
JS_ASSERT(pc->blockidGen < JS_BIT(20));
@ -102,8 +105,8 @@ PushStatementPC(ParseContext<ParseHandler> *pc, StmtInfoPC *stmt, StmtType type)
// See comment on member function declaration.
template <>
bool
ParseContext<FullParseHandler>::define(JSContext *cx, HandlePropertyName name,
ParseNode *pn, Definition::Kind kind)
ParseContext<FullParseHandler>::define(TokenStream &ts,
PropertyName *name, ParseNode *pn, Definition::Kind kind)
{
JS_ASSERT(!pn->isUsed());
JS_ASSERT_IF(pn->isDefn(), pn->isPlaceholder());
@ -154,11 +157,11 @@ ParseContext<FullParseHandler>::define(JSContext *cx, HandlePropertyName name,
JS_ASSERT(sc->isFunctionBox());
dn->setOp(JSOP_GETARG);
dn->pn_dflags |= PND_BOUND;
if (!dn->pn_cookie.set(cx, staticLevel, args_.length()))
if (!dn->pn_cookie.set(ts, staticLevel, args_.length()))
return false;
if (!args_.append(dn))
return false;
if (name == cx->names().empty)
if (name == ts.names().empty)
break;
if (!decls_.addUnique(name, dn))
return false;
@ -169,7 +172,7 @@ ParseContext<FullParseHandler>::define(JSContext *cx, HandlePropertyName name,
if (sc->isFunctionBox()) {
dn->setOp(JSOP_GETLOCAL);
dn->pn_dflags |= PND_BOUND;
if (!dn->pn_cookie.set(cx, staticLevel, vars_.length()))
if (!dn->pn_cookie.set(ts, staticLevel, vars_.length()))
return false;
if (!vars_.append(dn))
return false;
@ -195,7 +198,7 @@ ParseContext<FullParseHandler>::define(JSContext *cx, HandlePropertyName name,
template <>
bool
ParseContext<SyntaxParseHandler>::define(JSContext *cx, HandlePropertyName name, Node pn,
ParseContext<SyntaxParseHandler>::define(TokenStream &ts, PropertyName *name, Node pn,
Definition::Kind kind)
{
JS_ASSERT(!decls_.lookupFirst(name));
@ -296,12 +299,13 @@ AppendPackedBindings(const ParseContext<ParseHandler> *pc, const DeclVector &vec
template <typename ParseHandler>
bool
ParseContext<ParseHandler>::generateFunctionBindings(JSContext *cx, InternalHandle<Bindings*> bindings) const
ParseContext<ParseHandler>::generateFunctionBindings(ExclusiveContext *cx, LifoAlloc &alloc,
InternalHandle<Bindings*> bindings) const
{
JS_ASSERT(sc->isFunctionBox());
unsigned count = args_.length() + vars_.length();
Binding *packedBindings = cx->tempLifoAlloc().newArrayUninitialized<Binding>(count);
Binding *packedBindings = alloc.newArrayUninitialized<Binding>(count);
if (!packedBindings) {
js_ReportOutOfMemory(cx);
return false;
@ -380,47 +384,47 @@ Parser<SyntaxParseHandler>::abortIfSyntaxParser()
}
template <typename ParseHandler>
Parser<ParseHandler>::Parser(JSContext *cx, const CompileOptions &options,
Parser<ParseHandler>::Parser(ExclusiveContext *cx, LifoAlloc *alloc,
const CompileOptions &options,
const jschar *chars, size_t length, bool foldConstants,
Parser<SyntaxParseHandler> *syntaxParser,
LazyScript *lazyOuterFunction)
: AutoGCRooter(cx, PARSER),
context(cx),
alloc(*alloc),
tokenStream(cx, options, chars, length, thisForCtor(), keepAtoms),
traceListHead(NULL),
pc(NULL),
sct(NULL),
keepAtoms(cx->runtime()),
keepAtoms(cx->asJSContext()->runtime()),
foldConstants(foldConstants),
compileAndGo(options.compileAndGo),
selfHostingMode(options.selfHostingMode),
abortedSyntaxParse(false),
handler(cx, tokenStream, foldConstants, syntaxParser, lazyOuterFunction)
handler(cx, *alloc, tokenStream, foldConstants, syntaxParser, lazyOuterFunction)
{
cx->runtime()->activeCompilations++;
cx->asJSContext()->runtime()->activeCompilations++;
// The Mozilla specific JSOPTION_EXTRA_WARNINGS option adds extra warnings
// which are not generated if functions are parsed lazily. Note that the
// standard "use strict" does not inhibit lazy parsing.
if (context->hasExtraWarningsOption())
if (options.extraWarningsOption)
handler.disableSyntaxParser();
tempPoolMark = cx->tempLifoAlloc().mark();
tempPoolMark = alloc->mark();
}
template <typename ParseHandler>
Parser<ParseHandler>::~Parser()
{
JSContext *cx = context;
cx->tempLifoAlloc().release(tempPoolMark);
cx->runtime()->activeCompilations--;
context->asJSContext()->runtime()->activeCompilations--;
alloc.release(tempPoolMark);
/*
* The parser can allocate enormous amounts of memory for large functions.
* Eagerly free the memory now (which otherwise won't be freed until the
* next GC) to avoid unnecessary OOMs.
*/
cx->tempLifoAlloc().freeAllIfHugeAndUnused();
alloc.freeAllIfHugeAndUnused();
}
template <typename ParseHandler>
@ -437,7 +441,7 @@ Parser<ParseHandler>::newObjectBox(JSObject *obj)
* function.
*/
ObjectBox *objbox = context->tempLifoAlloc().new_<ObjectBox>(obj, traceListHead);
ObjectBox *objbox = alloc.new_<ObjectBox>(obj, traceListHead);
if (!objbox) {
js_ReportOutOfMemory(context);
return NULL;
@ -449,10 +453,10 @@ Parser<ParseHandler>::newObjectBox(JSObject *obj)
}
template <typename ParseHandler>
FunctionBox::FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fun,
ParseContext<ParseHandler> *outerpc, bool strict)
FunctionBox::FunctionBox(ExclusiveContext *cx, ObjectBox* traceListHead, JSFunction *fun,
ParseContext<ParseHandler> *outerpc, bool strict, bool extraWarnings)
: ObjectBox(fun, traceListHead),
SharedContext(cx, strict),
SharedContext(cx, strict, extraWarnings),
bindings(),
bufStart(0),
bufEnd(0),
@ -526,7 +530,8 @@ Parser<ParseHandler>::newFunctionBox(JSFunction *fun,
* function.
*/
FunctionBox *funbox =
context->tempLifoAlloc().new_<FunctionBox>(context, traceListHead, fun, outerpc, strict);
alloc.new_<FunctionBox>(context, traceListHead, fun, outerpc,
strict, options().extraWarningsOption);
if (!funbox) {
js_ReportOutOfMemory(context);
return NULL;
@ -537,10 +542,10 @@ Parser<ParseHandler>::newFunctionBox(JSFunction *fun,
return funbox;
}
ModuleBox::ModuleBox(JSContext *cx, ObjectBox *traceListHead, Module *module,
ParseContext<FullParseHandler> *pc)
: ObjectBox(module, traceListHead),
SharedContext(cx, true)
ModuleBox::ModuleBox(ExclusiveContext *cx, ObjectBox *traceListHead, Module *module,
ParseContext<FullParseHandler> *pc, bool extraWarnings)
: ObjectBox(module, traceListHead),
SharedContext(cx, true, extraWarnings)
{
}
@ -558,7 +563,8 @@ Parser<FullParseHandler>::newModuleBox(Module *module, ParseContext<FullParseHan
* function.
*/
ModuleBox *modulebox =
context->tempLifoAlloc().new_<ModuleBox>(context, traceListHead, module, outerpc);
alloc.new_<ModuleBox>(context, traceListHead, module, outerpc,
options().extraWarningsOption);
if (!modulebox) {
js_ReportOutOfMemory(context);
return NULL;
@ -597,7 +603,8 @@ Parser<ParseHandler>::parse(JSObject *chain)
* an object lock before it finishes generating bytecode into a script
* protected from the GC by a root or a stack frame reference.
*/
GlobalSharedContext globalsc(context, chain, StrictModeFromContext(context));
GlobalSharedContext globalsc(context, chain,
options().strictOption, options().extraWarningsOption);
ParseContext<ParseHandler> globalpc(this, NULL, &globalsc, /* staticLevel = */ 0, /* bodyid = */ 0);
if (!globalpc.init())
return null();
@ -757,7 +764,7 @@ Parser<ParseHandler>::reportBadReturn(Node pn, ParseReportKind kind,
JSAutoByteString name;
JSAtom *atom = pc->sc->asFunctionBox()->function()->atom();
if (atom) {
if (!js_AtomToPrintableString(context, atom, &name))
if (!AtomToPrintableString(context, atom, &name))
return false;
} else {
errnum = anonerrnum;
@ -792,7 +799,7 @@ Parser<ParseHandler>::checkStrictAssignment(Node lhs)
if (atom == context->names().eval || atom == context->names().arguments) {
JSAutoByteString name;
if (!js_AtomToPrintableString(context, atom, &name) ||
if (!AtomToPrintableString(context, atom, &name) ||
!report(ParseStrictError, pc->sc->strict, lhs,
JSMSG_DEPRECATED_ASSIGN, name.ptr()))
{
@ -817,7 +824,7 @@ Parser<ParseHandler>::checkStrictBinding(HandlePropertyName name, Node pn)
if (name == context->names().eval || name == context->names().arguments || IsKeyword(name)) {
JSAutoByteString bytes;
if (!js_AtomToPrintableString(context, name, &bytes))
if (!AtomToPrintableString(context, name, &bytes))
return false;
return report(ParseStrictError, pc->sc->strict, pn,
JSMSG_BAD_BINDING, bytes.ptr());
@ -865,14 +872,14 @@ Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoN
return null();
InternalHandle<Bindings*> scriptBindings(script, &script->bindings);
if (!funpc.generateFunctionBindings(context, scriptBindings))
if (!funpc.generateFunctionBindings(context, alloc, scriptBindings))
return null();
// Also populate the internal bindings of the function box, so that
// heavyweight tests while emitting bytecode work.
InternalHandle<Bindings*> funboxBindings =
InternalHandle<Bindings*>::fromMarkedLocation(&(*funbox)->bindings);
if (!funpc.generateFunctionBindings(context, funboxBindings))
if (!funpc.generateFunctionBindings(context, alloc, funboxBindings))
return null();
return pn;
@ -907,7 +914,7 @@ Parser<FullParseHandler>::checkFunctionArguments()
Definition *dn = r.front().value().get<FullParseHandler>();
pc->lexdeps->remove(arguments);
dn->pn_dflags |= PND_IMPLICITARGUMENTS;
if (!pc->define(context, arguments, dn, Definition::VAR))
if (!pc->define(tokenStream, arguments, dn, Definition::VAR))
return false;
pc->sc->asFunctionBox()->usesArguments = true;
break;
@ -936,7 +943,7 @@ Parser<FullParseHandler>::checkFunctionArguments()
ParseNode *pn = newName(arguments);
if (!pn)
return false;
if (!pc->define(context, arguments, pn, Definition::VAR))
if (!pc->define(tokenStream, arguments, pn, Definition::VAR))
return false;
argumentsHasBinding = true;
argumentsHasLocalBinding = true;
@ -1051,7 +1058,7 @@ Parser<ParseHandler>::functionBody(FunctionSyntaxKind kind, FunctionBodyType typ
}
/* Check for falling off the end of a function that returns a value. */
if (context->hasExtraWarningsOption() && pc->funHasReturnExpr && !checkFinalReturn(pn))
if (options().extraWarningsOption && pc->funHasReturnExpr && !checkFinalReturn(pn))
return null();
/* Define the 'arguments' binding if necessary. */
@ -1143,10 +1150,10 @@ Parser<FullParseHandler>::makeDefIntoUse(Definition *dn, ParseNode *pn, JSAtom *
template <typename ParseHandler>
struct BindData
{
BindData(JSContext *cx) : let(cx) {}
BindData(ExclusiveContext *cx) : let(cx) {}
typedef bool
(*Binder)(JSContext *cx, BindData *data, HandlePropertyName name, Parser<ParseHandler> *parser);
(*Binder)(BindData *data, HandlePropertyName name, Parser<ParseHandler> *parser);
/* name node for definition processing and error source coordinates */
typename ParseHandler::Node pn;
@ -1155,7 +1162,7 @@ struct BindData
Binder binder; /* binder, discriminates u */
struct LetData {
LetData(JSContext *cx) : blockObj(cx) {}
LetData(ExclusiveContext *cx) : blockObj(cx) {}
VarContext varContext;
RootedStaticBlockObject blockObj;
unsigned overflow;
@ -1203,12 +1210,12 @@ Parser<ParseHandler>::newFunction(GenericParseContext *pc, HandleAtom atom,
: JSFunction::INTERPRETED;
fun = NewFunction(context, NullPtr(), NULL, 0, flags, parent, atom,
JSFunction::FinalizeKind, MaybeSingletonObject);
if (selfHostingMode)
if (options().selfHostingMode)
fun->setIsSelfHostedBuiltin();
if (fun && !compileAndGo) {
if (!JSObject::clearParent(context, fun))
if (fun && !options().compileAndGo) {
if (!JSObject::clearParent(context->asJSContext(), fun))
return NULL;
if (!JSObject::clearType(context, fun))
if (!JSObject::clearType(context->asJSContext(), fun))
return NULL;
fun->setEnvironment(NULL);
}
@ -1216,18 +1223,18 @@ Parser<ParseHandler>::newFunction(GenericParseContext *pc, HandleAtom atom,
}
static bool
MatchOrInsertSemicolon(JSContext *cx, TokenStream *ts)
MatchOrInsertSemicolon(TokenStream &ts)
{
TokenKind tt = ts->peekTokenSameLine(TSF_OPERAND);
TokenKind tt = ts.peekTokenSameLine(TSF_OPERAND);
if (tt == TOK_ERROR)
return false;
if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) {
/* Advance the scanner for proper error location reporting. */
ts->getToken(TSF_OPERAND);
ts->reportError(JSMSG_SEMI_BEFORE_STMNT);
ts.getToken(TSF_OPERAND);
ts.reportError(JSMSG_SEMI_BEFORE_STMNT);
return false;
}
(void) ts->matchToken(TOK_SEMI);
(void) ts.matchToken(TOK_SEMI);
return true;
}
@ -1249,11 +1256,11 @@ Parser<ParseHandler>::getOrCreateLexicalDependency(ParseContext<ParseHandler> *p
}
static bool
ConvertDefinitionToNamedLambdaUse(JSContext *cx, ParseContext<FullParseHandler> *pc,
ConvertDefinitionToNamedLambdaUse(TokenStream &ts, ParseContext<FullParseHandler> *pc,
FunctionBox *funbox, Definition *dn)
{
dn->setOp(JSOP_CALLEE);
if (!dn->pn_cookie.set(cx, pc->staticLevel, UpvarCookie::CALLEE_SLOT))
if (!dn->pn_cookie.set(ts, pc->staticLevel, UpvarCookie::CALLEE_SLOT))
return false;
dn->pn_dflags |= PND_BOUND;
JS_ASSERT(dn->kind() == Definition::NAMED_LAMBDA);
@ -1302,7 +1309,7 @@ Parser<FullParseHandler>::leaveFunction(ParseNode *fn, HandlePropertyName funNam
JS_ASSERT(dn->isPlaceholder());
if (atom == funName && kind == Expression) {
if (!ConvertDefinitionToNamedLambdaUse(context, pc, funbox, dn))
if (!ConvertDefinitionToNamedLambdaUse(tokenStream, pc, funbox, dn))
return false;
continue;
}
@ -1380,7 +1387,7 @@ Parser<FullParseHandler>::leaveFunction(ParseNode *fn, HandlePropertyName funNam
InternalHandle<Bindings*> bindings =
InternalHandle<Bindings*>::fromMarkedLocation(&funbox->bindings);
return pc->generateFunctionBindings(context, bindings);
return pc->generateFunctionBindings(context, alloc, bindings);
}
template <>
@ -1428,7 +1435,7 @@ Parser<ParseHandler>::defineArg(Node funcpn, HandlePropertyName name,
*/
if (sc->needStrictChecks()) {
JSAutoByteString bytes;
if (!js_AtomToPrintableString(context, name, &bytes))
if (!AtomToPrintableString(context, name, &bytes))
return false;
if (!report(ParseStrictError, pc->sc->strict, pn,
JSMSG_DUPLICATE_FORMAL, bytes.ptr()))
@ -1458,13 +1465,13 @@ Parser<ParseHandler>::defineArg(Node funcpn, HandlePropertyName name,
return false;
handler.addFunctionArgument(funcpn, argpn);
return pc->define(context, name, argpn, Definition::ARG);
return pc->define(tokenStream, name, argpn, Definition::ARG);
}
#if JS_HAS_DESTRUCTURING
template <typename ParseHandler>
/* static */ bool
Parser<ParseHandler>::bindDestructuringArg(JSContext *cx, BindData<ParseHandler> *data,
Parser<ParseHandler>::bindDestructuringArg(BindData<ParseHandler> *data,
HandlePropertyName name, Parser<ParseHandler> *parser)
{
ParseContext<ParseHandler> *pc = parser->pc;
@ -1478,7 +1485,7 @@ Parser<ParseHandler>::bindDestructuringArg(JSContext *cx, BindData<ParseHandler>
if (!parser->checkStrictBinding(name, data->pn))
return false;
return pc->define(cx, name, data->pn, Definition::VAR);
return pc->define(parser->tokenStream, name, data->pn, Definition::VAR);
}
#endif /* JS_HAS_DESTRUCTURING */
@ -1569,7 +1576,7 @@ Parser<ParseHandler>::functionArguments(FunctionSyntaxKind kind, Node *listp, No
if (!rhs)
return false;
if (!pc->define(context, name, rhs, Definition::ARG))
if (!pc->define(tokenStream, name, rhs, Definition::ARG))
return false;
Node item = handler.newBinary(PNK_ASSIGN, lhs, rhs);
@ -1676,12 +1683,12 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
JS_ASSERT(!dn->isUsed());
JS_ASSERT(dn->isDefn());
if (context->hasExtraWarningsOption() || dn->kind() == Definition::CONST) {
if (options().extraWarningsOption || dn->kind() == Definition::CONST) {
JSAutoByteString name;
ParseReportKind reporter = (dn->kind() != Definition::CONST)
? ParseExtraWarning
: ParseError;
if (!js_AtomToPrintableString(context, funName, &name) ||
if (!AtomToPrintableString(context, funName, &name) ||
!report(reporter, false, NULL, JSMSG_REDECLARED_VAR,
Definition::kindString(dn->kind()), name.ptr()))
{
@ -1720,7 +1727,7 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
pn = fn;
}
if (!pc->define(context, funName, pn, Definition::VAR))
if (!pc->define(tokenStream, funName, pn, Definition::VAR))
return false;
}
@ -1865,7 +1872,7 @@ Parser<SyntaxParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
if (DefinitionNode dn = pc->decls().lookupFirst(funName)) {
if (dn == Definition::CONST) {
JSAutoByteString name;
if (!js_AtomToPrintableString(context, funName, &name) ||
if (!AtomToPrintableString(context, funName, &name) ||
!report(ParseError, false, null(), JSMSG_REDECLARED_VAR,
Definition::kindString(dn), name.ptr()))
{
@ -1876,7 +1883,7 @@ Parser<SyntaxParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
if (pc->lexdeps.lookupDefn<SyntaxParseHandler>(funName))
pc->lexdeps->remove(funName);
if (!pc->define(context, funName, *pn, Definition::VAR))
if (!pc->define(tokenStream, funName, *pn, Definition::VAR))
return false;
}
@ -2177,14 +2184,14 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, unsigned st
if (fun->isNamedLambda()) {
if (AtomDefnPtr p = pc->lexdeps->lookup(funName)) {
Definition *dn = p.value().get<FullParseHandler>();
if (!ConvertDefinitionToNamedLambdaUse(context, pc, funbox, dn))
if (!ConvertDefinitionToNamedLambdaUse(tokenStream, pc, funbox, dn))
return NULL;
}
}
InternalHandle<Bindings*> bindings =
InternalHandle<Bindings*>::fromMarkedLocation(&funbox->bindings);
if (!pc->generateFunctionBindings(context, bindings))
if (!pc->generateFunctionBindings(context, alloc, bindings))
return null();
return pn;
@ -2267,7 +2274,7 @@ Parser<ParseHandler>::functionArgsAndBodyGeneric(Node pn, HandleFunction fun,
if (tokenStream.hadError())
return false;
funbox->bufEnd = pos().end;
if (kind == Statement && !MatchOrInsertSemicolon(context, &tokenStream))
if (kind == Statement && !MatchOrInsertSemicolon(tokenStream))
return false;
}
#endif
@ -2279,7 +2286,7 @@ template <>
ParseNode *
Parser<FullParseHandler>::moduleDecl()
{
JS_ASSERT(tokenStream.currentToken().name() == context->runtime()->atomState.module);
JS_ASSERT(tokenStream.currentToken().name() == context->names().module);
if (!((pc->sc->isGlobalSharedContext() || pc->sc->isModuleBox()) && pc->atBodyLevel()))
{
report(ParseError, false, NULL, JSMSG_MODULE_STATEMENT);
@ -2421,7 +2428,7 @@ Parser<ParseHandler>::maybeParseDirective(Node pn, bool *cont)
// in other browsers first.
handler.setPrologue(pn);
if (directive == context->runtime()->atomState.useStrict) {
if (directive == context->names().useStrict) {
// We're going to be in strict mode. Note that this scope explicitly
// had "use strict";
pc->sc->setExplicitUseStrict();
@ -2531,14 +2538,14 @@ Parser<ParseHandler>::condition()
}
static bool
MatchLabel(JSContext *cx, TokenStream *ts, MutableHandlePropertyName label)
MatchLabel(TokenStream &ts, MutableHandlePropertyName label)
{
TokenKind tt = ts->peekTokenSameLine(TSF_OPERAND);
TokenKind tt = ts.peekTokenSameLine(TSF_OPERAND);
if (tt == TOK_ERROR)
return false;
if (tt == TOK_NAME) {
(void) ts->getToken();
label.set(ts->currentToken().name());
(void) ts.getToken();
label.set(ts.currentToken().name());
} else {
label.set(NULL);
}
@ -2550,7 +2557,7 @@ bool
Parser<ParseHandler>::reportRedeclaration(Node pn, bool isConst, JSAtom *atom)
{
JSAutoByteString name;
if (js_AtomToPrintableString(context, atom, &name))
if (AtomToPrintableString(context, atom, &name))
report(ParseError, false, pn, JSMSG_REDECLARED_VAR, isConst ? "const" : "variable", name.ptr());
return false;
}
@ -2566,7 +2573,7 @@ Parser<ParseHandler>::reportRedeclaration(Node pn, bool isConst, JSAtom *atom)
*/
template <>
/* static */ bool
Parser<FullParseHandler>::bindLet(JSContext *cx, BindData<FullParseHandler> *data,
Parser<FullParseHandler>::bindLet(BindData<FullParseHandler> *data,
HandlePropertyName name, Parser<FullParseHandler> *parser)
{
ParseContext<FullParseHandler> *pc = parser->pc;
@ -2574,6 +2581,8 @@ Parser<FullParseHandler>::bindLet(JSContext *cx, BindData<FullParseHandler> *dat
if (!parser->checkStrictBinding(name, pn))
return false;
ExclusiveContext *cx = parser->context;
Rooted<StaticBlockObject *> blockObj(cx, data->let.blockObj);
unsigned blockCount = blockObj->slotCount();
if (blockCount == JS_BIT(16)) {
@ -2588,7 +2597,7 @@ Parser<FullParseHandler>::bindLet(JSContext *cx, BindData<FullParseHandler> *dat
* and eval code, js::frontend::CompileScript will adjust the slot
* again to include script->nfixed.
*/
if (!pn->pn_cookie.set(parser->context, pc->staticLevel, uint16_t(blockCount)))
if (!pn->pn_cookie.set(parser->tokenStream, pc->staticLevel, uint16_t(blockCount)))
return false;
/*
@ -2600,7 +2609,7 @@ Parser<FullParseHandler>::bindLet(JSContext *cx, BindData<FullParseHandler> *dat
Definition *dn = pc->decls().lookupFirst(name);
if (dn && dn->pn_blockid == pc->blockid())
return parser->reportRedeclaration(pn, dn->isConst(), name);
if (!pc->define(cx, name, pn, Definition::LET))
if (!pc->define(parser->tokenStream, name, pn, Definition::LET))
return false;
}
@ -2624,7 +2633,7 @@ Parser<FullParseHandler>::bindLet(JSContext *cx, BindData<FullParseHandler> *dat
template <>
/* static */ bool
Parser<SyntaxParseHandler>::bindLet(JSContext *cx, BindData<SyntaxParseHandler> *data,
Parser<SyntaxParseHandler>::bindLet(BindData<SyntaxParseHandler> *data,
HandlePropertyName name, Parser<SyntaxParseHandler> *parser)
{
return true;
@ -2632,17 +2641,17 @@ Parser<SyntaxParseHandler>::bindLet(JSContext *cx, BindData<SyntaxParseHandler>
template <typename ParseHandler, class Op>
static inline bool
ForEachLetDef(JSContext *cx, ParseContext<ParseHandler> *pc,
ForEachLetDef(TokenStream &ts, ParseContext<ParseHandler> *pc,
HandleStaticBlockObject blockObj, Op op)
{
for (Shape::Range<CanGC> r(cx, blockObj->lastProperty()); !r.empty(); r.popFront()) {
for (Shape::Range<CanGC> r(ts.context(), blockObj->lastProperty()); !r.empty(); r.popFront()) {
Shape &shape = r.front();
/* Beware the destructuring dummy slots. */
if (JSID_IS_INT(shape.propid()))
continue;
if (!op(cx, pc, blockObj, shape, JSID_TO_ATOM(shape.propid())))
if (!op(ts, pc, blockObj, shape, JSID_TO_ATOM(shape.propid())))
return false;
}
return true;
@ -2650,7 +2659,7 @@ ForEachLetDef(JSContext *cx, ParseContext<ParseHandler> *pc,
template <typename ParseHandler>
struct PopLetDecl {
bool operator()(JSContext *, ParseContext<ParseHandler> *pc, HandleStaticBlockObject,
bool operator()(TokenStream &, ParseContext<ParseHandler> *pc, HandleStaticBlockObject,
const Shape &, JSAtom *atom)
{
pc->popLetDecl(atom);
@ -2660,16 +2669,16 @@ struct PopLetDecl {
template <typename ParseHandler>
static void
PopStatementPC(JSContext *cx, ParseContext<ParseHandler> *pc)
PopStatementPC(TokenStream &ts, ParseContext<ParseHandler> *pc)
{
RootedStaticBlockObject blockObj(cx, pc->topStmt->blockObj);
RootedStaticBlockObject blockObj(ts.context(), pc->topStmt->blockObj);
JS_ASSERT(!!blockObj == (pc->topStmt->isBlockScope));
FinishPopStatement(pc);
if (blockObj) {
JS_ASSERT(!blockObj->inDictionaryMode());
ForEachLetDef(cx, pc, blockObj, PopLetDecl<ParseHandler>());
ForEachLetDef(ts, pc, blockObj, PopLetDecl<ParseHandler>());
blockObj->resetPrevBlockChainFromParser();
}
}
@ -2735,9 +2744,10 @@ OuterLet(ParseContext<ParseHandler> *pc, StmtInfoPC *stmt, HandleAtom atom)
template <typename ParseHandler>
/* static */ bool
Parser<ParseHandler>::bindVarOrConst(JSContext *cx, BindData<ParseHandler> *data,
Parser<ParseHandler>::bindVarOrConst(BindData<ParseHandler> *data,
HandlePropertyName name, Parser<ParseHandler> *parser)
{
ExclusiveContext *cx = parser->context;
ParseContext<ParseHandler> *pc = parser->pc;
Node pn = data->pn;
bool isConstDecl = data->op == JSOP_DEFCONST;
@ -2772,8 +2782,10 @@ Parser<ParseHandler>::bindVarOrConst(JSContext *cx, BindData<ParseHandler> *data
DefinitionList::Range defs = pc->decls().lookupMulti(name);
JS_ASSERT_IF(stmt, !defs.empty());
if (defs.empty())
return pc->define(cx, name, pn, isConstDecl ? Definition::CONST : Definition::VAR);
if (defs.empty()) {
return pc->define(parser->tokenStream, name, pn,
isConstDecl ? Definition::CONST : Definition::VAR);
}
/*
* There was a previous declaration with the same name. The standard
@ -2786,7 +2798,7 @@ Parser<ParseHandler>::bindVarOrConst(JSContext *cx, BindData<ParseHandler> *data
Definition::Kind dn_kind = parser->handler.getDefinitionKind(dn);
if (dn_kind == Definition::ARG) {
JSAutoByteString bytes;
if (!js_AtomToPrintableString(cx, name, &bytes))
if (!AtomToPrintableString(cx, name, &bytes))
return false;
if (isConstDecl) {
@ -2801,13 +2813,13 @@ Parser<ParseHandler>::bindVarOrConst(JSContext *cx, BindData<ParseHandler> *data
(dn_kind == Definition::LET &&
(stmt->type != STMT_CATCH || OuterLet(pc, stmt, name))));
if (cx->hasExtraWarningsOption()
if (parser->options().extraWarningsOption
? data->op != JSOP_DEFVAR || dn_kind != Definition::VAR
: error)
{
JSAutoByteString bytes;
ParseReportKind reporter = error ? ParseError : ParseExtraWarning;
if (!js_AtomToPrintableString(cx, name, &bytes) ||
if (!AtomToPrintableString(cx, name, &bytes) ||
!parser->report(reporter, false, pn, JSMSG_REDECLARED_VAR,
Definition::kindString(dn_kind), bytes.ptr()))
{
@ -2879,7 +2891,7 @@ Parser<FullParseHandler>::bindDestructuringVar(BindData<FullParseHandler> *data,
RootedPropertyName name(context, pn->pn_atom->asPropertyName());
data->pn = pn;
if (!data->binder(context, data, name, this))
if (!data->binder(data, name, this))
return false;
/*
@ -3164,13 +3176,13 @@ struct AddLetDecl
AddLetDecl(uint32_t blockid) : blockid(blockid) {}
bool operator()(JSContext *cx, ParseContext<FullParseHandler> *pc,
bool operator()(TokenStream &ts, ParseContext<FullParseHandler> *pc,
HandleStaticBlockObject blockObj, const Shape &shape, JSAtom *)
{
ParseNode *def = (ParseNode *) blockObj->getSlot(shape.slot()).toPrivate();
def->pn_blockid = blockid;
RootedPropertyName name(cx, def->name());
return pc->define(cx, name, def, Definition::LET);
RootedPropertyName name(ts.context(), def->name());
return pc->define(ts, name, def, Definition::LET);
}
};
@ -3187,7 +3199,7 @@ Parser<FullParseHandler>::pushLetScope(HandleStaticBlockObject blockObj, StmtInf
pn->pn_dflags |= PND_LET;
/* Populate the new scope with decls found in the head with updated blockid. */
if (!ForEachLetDef(context, pc, blockObj, AddLetDecl(stmt->blockid)))
if (!ForEachLetDef(tokenStream, pc, blockObj, AddLetDecl(stmt->blockid)))
return null();
return pn;
@ -3274,12 +3286,12 @@ Parser<ParseHandler>::letBlock(LetContext letContext)
return null();
}
handler.setLeaveBlockResult(block, expr, letContext != LetStatement);
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
handler.setEndPosition(pnlet, pos().end);
if (needExprStmt) {
if (!MatchOrInsertSemicolon(context, &tokenStream))
if (!MatchOrInsertSemicolon(tokenStream))
return null();
return handler.newExprStatement(pnlet, pos().end);
}
@ -3311,7 +3323,7 @@ Parser<ParseHandler>::blockStatement()
return null();
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_COMPOUND);
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
return list;
}
@ -3443,7 +3455,7 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
if (data.op == JSOP_DEFCONST)
handler.setFlag(pn2, PND_CONST);
data.pn = pn2;
if (!data.binder(context, &data, name, this))
if (!data.binder(&data, name, this))
return null();
handler.addList(pn, pn2);
@ -3574,7 +3586,7 @@ Parser<FullParseHandler>::letStatement()
} while (0);
/* Check termination of this primitive statement. */
return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL;
return MatchOrInsertSemicolon(tokenStream) ? pn : NULL;
}
template <>
@ -3595,7 +3607,7 @@ Parser<ParseHandler>::expressionStatement()
Node pnexpr = expr();
if (!pnexpr)
return null();
if (!MatchOrInsertSemicolon(context, &tokenStream))
if (!MatchOrInsertSemicolon(tokenStream))
return null();
return handler.newExprStatement(pnexpr, pos().end);
}
@ -3633,7 +3645,7 @@ Parser<ParseHandler>::ifStatement()
elseBranch = null();
}
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
return handler.newIfStatement(begin, cond, thenBranch, elseBranch);
}
@ -3651,12 +3663,12 @@ Parser<ParseHandler>::doWhileStatement()
Node cond = condition();
if (!cond)
return null();
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
if (versionNumber() == JSVERSION_ECMA_3) {
// Pedantically require a semicolon or line break, following ES3.
// Bug 880329 proposes removing this case.
if (!MatchOrInsertSemicolon(context, &tokenStream))
if (!MatchOrInsertSemicolon(tokenStream))
return null();
} else {
// The semicolon after do-while is even more optional than most
@ -3683,7 +3695,7 @@ Parser<ParseHandler>::whileStatement()
Node body = statement();
if (!body)
return null();
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
return handler.newWhileStatement(begin, cond, body);
}
@ -4049,9 +4061,9 @@ Parser<FullParseHandler>::forStatement()
#if JS_HAS_BLOCK_SCOPE
if (blockObj)
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
#endif
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
ParseNode *forLoop = handler.newForStatement(begin, forHead, body, iflags);
if (!forLoop)
@ -4187,7 +4199,7 @@ Parser<SyntaxParseHandler>::forStatement()
if (!statement())
return null();
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
return SyntaxParseHandler::NodeGeneric;
}
@ -4282,7 +4294,7 @@ Parser<ParseHandler>::switchStatement()
caseList = pc->blockNode;
pc->blockNode = saveBlock;
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
handler.setEndPosition(caseList, pos().end);
@ -4297,7 +4309,7 @@ Parser<ParseHandler>::continueStatement()
uint32_t begin = pos().begin;
RootedPropertyName label(context);
if (!MatchLabel(context, &tokenStream, &label))
if (!MatchLabel(tokenStream, &label))
return null();
StmtInfoPC *stmt = pc->topStmt;
@ -4330,7 +4342,7 @@ Parser<ParseHandler>::continueStatement()
}
}
if (!MatchOrInsertSemicolon(context, &tokenStream))
if (!MatchOrInsertSemicolon(tokenStream))
return null();
return handler.newContinueStatement(label, TokenPos(begin, pos().end));
@ -4344,7 +4356,7 @@ Parser<ParseHandler>::breakStatement()
uint32_t begin = pos().begin;
RootedPropertyName label(context);
if (!MatchLabel(context, &tokenStream, &label))
if (!MatchLabel(tokenStream, &label))
return null();
StmtInfoPC *stmt = pc->topStmt;
if (label) {
@ -4367,7 +4379,7 @@ Parser<ParseHandler>::breakStatement()
}
}
if (!MatchOrInsertSemicolon(context, &tokenStream))
if (!MatchOrInsertSemicolon(tokenStream))
return null();
return handler.newBreakStatement(label, TokenPos(begin, pos().end));
@ -4435,7 +4447,7 @@ Parser<ParseHandler>::returnStatementOrYieldExpression()
}
if (!isYield) {
if (!MatchOrInsertSemicolon(context, &tokenStream))
if (!MatchOrInsertSemicolon(tokenStream))
return null();
}
@ -4452,7 +4464,7 @@ Parser<ParseHandler>::returnStatementOrYieldExpression()
return null();
}
if (context->hasExtraWarningsOption() && pc->funHasReturnExpr && pc->funHasReturnVoid &&
if (options().extraWarningsOption && pc->funHasReturnExpr && pc->funHasReturnVoid &&
!reportBadReturn(pn, ParseExtraWarning,
JSMSG_NO_RETURN_VALUE, JSMSG_ANON_NO_RETURN_VALUE))
{
@ -4498,7 +4510,7 @@ Parser<FullParseHandler>::withStatement()
Node innerBlock = statement();
if (!innerBlock)
return null();
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
pc->sc->setBindingsAccessedDynamically();
pc->parsingWith = oldParsingWith;
@ -4548,7 +4560,7 @@ Parser<ParseHandler>::labeledStatement()
return null();
/* Pop the label, set pn_expr, and return early. */
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
return handler.newLabeledStatement(label, pn, begin);
}
@ -4573,7 +4585,7 @@ Parser<ParseHandler>::throwStatement()
if (!throwExpr)
return null();
if (!MatchOrInsertSemicolon(context, &tokenStream))
if (!MatchOrInsertSemicolon(tokenStream))
return null();
return handler.newThrowStatement(throwExpr, TokenPos(begin, pos().end));
@ -4612,7 +4624,7 @@ Parser<ParseHandler>::tryStatement()
if (!innerBlock)
return null();
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_TRY);
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
bool hasUnconditionalCatch = false;
Node catchList = null();
@ -4677,7 +4689,7 @@ Parser<ParseHandler>::tryStatement()
if (!catchName)
return null();
data.pn = catchName;
if (!data.binder(context, &data, label, this))
if (!data.binder(&data, label, this))
return null();
break;
}
@ -4707,7 +4719,7 @@ Parser<ParseHandler>::tryStatement()
if (!catchBody)
return null();
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_CATCH);
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
if (!catchGuard)
hasUnconditionalCatch = true;
@ -4731,7 +4743,7 @@ Parser<ParseHandler>::tryStatement()
if (!finallyBlock)
return null();
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_FINALLY);
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
} else {
tokenStream.ungetToken();
}
@ -4749,7 +4761,7 @@ Parser<ParseHandler>::debuggerStatement()
{
TokenPos p;
p.begin = pos().begin;
if (!MatchOrInsertSemicolon(context, &tokenStream))
if (!MatchOrInsertSemicolon(tokenStream))
return null();
p.end = pos().end;
@ -4860,7 +4872,7 @@ Parser<ParseHandler>::statement(bool canHaveDirectives)
}
/* Check termination of this primitive statement. */
return MatchOrInsertSemicolon(context, &tokenStream) ? pn : null();
return MatchOrInsertSemicolon(tokenStream) ? pn : null();
}
template <>
@ -5514,23 +5526,23 @@ GenexpGuard<ParseHandler>::maybeNoteGenerator(Node pn)
*/
template <typename ParseHandler>
static bool
BumpStaticLevel(ParseNode *pn, ParseContext<ParseHandler> *pc)
BumpStaticLevel(TokenStream &ts, ParseNode *pn, ParseContext<ParseHandler> *pc)
{
if (pn->pn_cookie.isFree())
return true;
unsigned level = unsigned(pn->pn_cookie.level()) + 1;
JS_ASSERT(level >= pc->staticLevel);
return pn->pn_cookie.set(pc->sc->context, level, pn->pn_cookie.slot());
return pn->pn_cookie.set(ts, level, pn->pn_cookie.slot());
}
template <typename ParseHandler>
static bool
AdjustBlockId(ParseNode *pn, unsigned adjust, ParseContext<ParseHandler> *pc)
AdjustBlockId(TokenStream &ts, ParseNode *pn, unsigned adjust, ParseContext<ParseHandler> *pc)
{
JS_ASSERT(pn->isArity(PN_LIST) || pn->isArity(PN_CODE) || pn->isArity(PN_NAME));
if (JS_BIT(20) - pn->pn_blockid <= adjust + 1) {
JS_ReportErrorNumber(pc->sc->context, js_GetErrorMessage, NULL, JSMSG_NEED_DIET, "program");
ts.reportError(JSMSG_NEED_DIET, "program");
return false;
}
pn->pn_blockid += adjust;
@ -5554,7 +5566,7 @@ CompExprTransplanter::transplant(ParseNode *pn)
return false;
}
if (pn->pn_pos >= root->pn_pos) {
if (!AdjustBlockId(pn, adjust, pc))
if (!AdjustBlockId(parser->tokenStream, pn, adjust, pc))
return false;
}
break;
@ -5588,7 +5600,7 @@ CompExprTransplanter::transplant(ParseNode *pn)
return false;
if (pn->isDefn()) {
if (genexp && !BumpStaticLevel(pn, pc))
if (genexp && !BumpStaticLevel(parser->tokenStream, pn, pc))
return false;
} else if (pn->isUsed()) {
JS_ASSERT(pn->pn_cookie.isFree());
@ -5606,9 +5618,9 @@ CompExprTransplanter::transplant(ParseNode *pn)
* will be visited further below.
*/
if (dn->isPlaceholder() && dn->pn_pos >= root->pn_pos && dn->dn_uses == pn) {
if (genexp && !BumpStaticLevel(dn, pc))
if (genexp && !BumpStaticLevel(parser->tokenStream, dn, pc))
return false;
if (!AdjustBlockId(dn, adjust, pc))
if (!AdjustBlockId(parser->tokenStream, dn, adjust, pc))
return false;
}
@ -5673,9 +5685,9 @@ CompExprTransplanter::transplant(ParseNode *pn)
* to only bump the definition once.
*/
if (genexp && !visitedImplicitArguments.has(dn)) {
if (!BumpStaticLevel(dn, pc))
if (!BumpStaticLevel(parser->tokenStream, dn, pc))
return false;
if (!AdjustBlockId(dn, adjust, pc))
if (!AdjustBlockId(parser->tokenStream, dn, adjust, pc))
return false;
if (!visitedImplicitArguments.put(dn))
return false;
@ -5685,7 +5697,7 @@ CompExprTransplanter::transplant(ParseNode *pn)
}
if (pn->pn_pos >= root->pn_pos) {
if (!AdjustBlockId(pn, adjust, pc))
if (!AdjustBlockId(parser->tokenStream, pn, adjust, pc))
return false;
}
break;
@ -5891,7 +5903,7 @@ Parser<FullParseHandler>::comprehensionTail(ParseNode *kid, unsigned blockid, bo
case TOK_NAME:
data.pn = pn3;
if (!data.binder(context, &data, name, this))
if (!data.binder(&data, name, this))
return null();
break;
@ -5940,7 +5952,7 @@ Parser<FullParseHandler>::comprehensionTail(ParseNode *kid, unsigned blockid, bo
pn2->pn_kid = kid;
*pnp = pn2;
PopStatementPC(context, pc);
PopStatementPC(tokenStream, pc);
return pn;
}
@ -6660,7 +6672,7 @@ Parser<ParseHandler>::primaryExpr(TokenKind tt)
(oldAssignType != VALUE || assignType != VALUE || pc->sc->needStrictChecks()))
{
JSAutoByteString name;
if (!js_AtomToPrintableString(context, atom, &name))
if (!AtomToPrintableString(context, atom, &name))
return null();
ParseReportKind reportKind =

View File

@ -29,7 +29,7 @@ struct StmtInfoPC : public StmtInfoBase {
uint32_t blockid; /* for simplified dominance computation */
StmtInfoPC(JSContext *cx) : StmtInfoBase(cx) {}
StmtInfoPC(ExclusiveContext *cx) : StmtInfoBase(cx) {}
};
typedef HashSet<JSAtom *> FuncStmtSet;
@ -155,7 +155,7 @@ struct ParseContext : public GenericParseContext
* 'pn' if they are in the scope of 'pn'.
* + Pre-existing placeholders in the scope of 'pn' have been removed.
*/
bool define(JSContext *cx, HandlePropertyName name, Node pn, Definition::Kind);
bool define(TokenStream &ts, PropertyName *name, Node pn, Definition::Kind);
/*
* Let definitions may shadow same-named definitions in enclosing scopes.
@ -187,7 +187,8 @@ struct ParseContext : public GenericParseContext
* - Sometimes a script's bindings are accessed at runtime to retrieve the
* contents of the lexical scope (e.g., from the debugger).
*/
bool generateFunctionBindings(JSContext *cx, InternalHandle<Bindings*> bindings) const;
bool generateFunctionBindings(ExclusiveContext *cx, LifoAlloc &alloc,
InternalHandle<Bindings*> bindings) const;
public:
uint32_t yieldOffset; /* offset of a yield expression that might
@ -240,7 +241,7 @@ struct ParseContext : public GenericParseContext
parenDepth(0),
yieldCount(0),
blockNode(ParseHandler::null()),
decls_(prs->context),
decls_(prs->context, prs->alloc),
args_(prs->context),
vars_(prs->context),
yieldOffset(0),
@ -304,7 +305,9 @@ template <typename ParseHandler>
class Parser : private AutoGCRooter, public StrictModeGetter
{
public:
JSContext *const context; /* FIXME Bug 551291: use AutoGCRooter::context? */
ExclusiveContext *const context;
LifoAlloc &alloc;
TokenStream tokenStream;
LifoAlloc::Mark tempPoolMark;
@ -323,25 +326,6 @@ class Parser : private AutoGCRooter, public StrictModeGetter
const bool foldConstants:1;
private:
/* Script can optimize name references based on scope chain. */
const bool compileAndGo:1;
/*
* In self-hosting mode, scripts emit JSOP_CALLINTRINSIC instead of
* JSOP_NAME or JSOP_GNAME to access unbound variables. JSOP_CALLINTRINSIC
* does a name lookup in a special object that contains properties
* installed during global initialization and that properties from
* self-hosted scripts get copied into lazily upon first access in a
* global.
* As that object is inaccessible to client code, the lookups are
* guaranteed to return the original objects, ensuring safe implementation
* of self-hosted builtins.
* Additionally, the special syntax _CallFunction(receiver, ...args, fun)
* is supported, for which bytecode is emitted that invokes |fun| with
* |receiver| as the this-object and ...args as the arguments..
*/
const bool selfHostingMode:1;
/*
* Not all language constructs can be handled during syntax parsing. If it
* is not known whether the parse succeeds or fails, this bit is set and
@ -364,7 +348,7 @@ class Parser : private AutoGCRooter, public StrictModeGetter
bool reportWithOffset(ParseReportKind kind, bool strict, uint32_t offset, unsigned errorNumber,
...);
Parser(JSContext *cx, const CompileOptions &options,
Parser(ExclusiveContext *cx, LifoAlloc *alloc, const CompileOptions &options,
const jschar *chars, size_t length, bool foldConstants,
Parser<SyntaxParseHandler> *syntaxParser,
LazyScript *lazyOuterFunction);
@ -439,6 +423,10 @@ class Parser : private AutoGCRooter, public StrictModeGetter
virtual bool strictMode() { return pc->sc->strict; }
const CompileOptions &options() const {
return tokenStream.options();
}
private:
/*
* JS parsers, from lowest to highest precedence.
@ -563,15 +551,15 @@ class Parser : private AutoGCRooter, public StrictModeGetter
}
static bool
bindDestructuringArg(JSContext *cx, BindData<ParseHandler> *data,
bindDestructuringArg(BindData<ParseHandler> *data,
HandlePropertyName name, Parser<ParseHandler> *parser);
static bool
bindLet(JSContext *cx, BindData<ParseHandler> *data,
bindLet(BindData<ParseHandler> *data,
HandlePropertyName name, Parser<ParseHandler> *parser);
static bool
bindVarOrConst(JSContext *cx, BindData<ParseHandler> *data,
bindVarOrConst(BindData<ParseHandler> *data,
HandlePropertyName name, Parser<ParseHandler> *parser);
static Node null() { return ParseHandler::null(); }

View File

@ -16,7 +16,7 @@ namespace frontend {
inline bool
SharedContext::needStrictChecks()
{
return context->hasExtraWarningsOption() || strict;
return strict || extraWarnings;
}
} /* namespace frontend */

View File

@ -149,16 +149,18 @@ class GlobalSharedContext;
class SharedContext
{
public:
JSContext *const context;
ExclusiveContext *const context;
AnyContextFlags anyCxFlags;
bool strict;
bool extraWarnings;
// If it's function code, funbox must be non-NULL and scopeChain must be NULL.
// If it's global code, funbox must be NULL.
SharedContext(JSContext *cx, bool strict)
SharedContext(ExclusiveContext *cx, bool strict, bool extraWarnings)
: context(cx),
anyCxFlags(),
strict(strict)
strict(strict),
extraWarnings(extraWarnings)
{}
virtual ObjectBox *toObjectBox() = 0;
@ -187,8 +189,9 @@ class GlobalSharedContext : public SharedContext
const RootedObject scopeChain_; /* scope chain object for the script */
public:
GlobalSharedContext(JSContext *cx, JSObject *scopeChain, bool strict)
: SharedContext(cx, strict),
GlobalSharedContext(ExclusiveContext *cx, JSObject *scopeChain,
bool strict, bool extraWarnings)
: SharedContext(cx, strict, extraWarnings),
scopeChain_(cx, scopeChain)
{}
@ -208,8 +211,8 @@ class ModuleBox : public ObjectBox, public SharedContext
public:
Bindings bindings;
ModuleBox(JSContext *cx, ObjectBox *traceListHead, Module *module,
ParseContext<FullParseHandler> *pc);
ModuleBox(ExclusiveContext *cx, ObjectBox *traceListHead, Module *module,
ParseContext<FullParseHandler> *pc, bool extraWarnings);
ObjectBox *toObjectBox() { return this; }
Module *module() const { return &object->as<Module>(); }
};
@ -243,8 +246,9 @@ class FunctionBox : public ObjectBox, public SharedContext
FunctionContextFlags funCxFlags;
template <typename ParseHandler>
FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fun, ParseContext<ParseHandler> *pc,
bool strict);
FunctionBox(ExclusiveContext *cx, ObjectBox* traceListHead, JSFunction *fun,
ParseContext<ParseHandler> *pc,
bool strict, bool extraWarnings);
ObjectBox *toObjectBox() { return this; }
JSFunction *function() const { return &object->as<JSFunction>(); }
@ -361,7 +365,7 @@ struct StmtInfoBase {
RootedAtom label; /* name of LABEL */
Rooted<StaticBlockObject *> blockObj; /* block scope object */
StmtInfoBase(JSContext *cx)
StmtInfoBase(ExclusiveContext *cx)
: isBlockScope(false), isForLetBlock(false), label(cx), blockObj(cx)
{}

View File

@ -42,7 +42,8 @@ class SyntaxParseHandler
};
typedef Definition::Kind DefinitionNode;
SyntaxParseHandler(JSContext *cx, TokenStream &tokenStream, bool foldConstants,
SyntaxParseHandler(ExclusiveContext *cx, LifoAlloc &alloc,
TokenStream &tokenStream, bool foldConstants,
Parser<SyntaxParseHandler> *syntaxParser, LazyScript *lazyOuterFunction)
: lastAtom(NULL),
tokenStream(tokenStream)

View File

@ -117,7 +117,7 @@ frontend::IsKeyword(JSLinearString *str)
return FindKeyword(str->chars(), str->length()) != NULL;
}
TokenStream::SourceCoords::SourceCoords(JSContext *cx, uint32_t ln)
TokenStream::SourceCoords::SourceCoords(ExclusiveContext *cx, uint32_t ln)
: lineStartOffsets_(cx), initialLineNum_(ln), lastLineIndex_(0)
{
// This is actually necessary! Removing it causes compile errors on
@ -262,10 +262,11 @@ TokenStream::SourceCoords::lineNumAndColumnIndex(uint32_t offset, uint32_t *line
#endif
/* Initialize members that aren't initialized in |init|. */
TokenStream::TokenStream(JSContext *cx, const CompileOptions &options,
TokenStream::TokenStream(ExclusiveContext *cx, const CompileOptions &options,
const jschar *base, size_t length, StrictModeGetter *smg,
AutoKeepAtoms& keepAtoms)
: srcCoords(cx, options.lineno),
options_(options),
tokens(),
cursor(),
lookahead(),
@ -276,9 +277,7 @@ TokenStream::TokenStream(JSContext *cx, const CompileOptions &options,
userbuf(cx, base - options.column, length + options.column), // See comment below
filename(options.filename),
sourceMap(NULL),
listenerTSData(),
tokenbuf(cx),
version(options.version),
cx(cx),
originPrincipals(JSScript::normalizeOriginPrincipals(options.principals,
options.originPrincipals)),
@ -293,14 +292,19 @@ TokenStream::TokenStream(JSContext *cx, const CompileOptions &options,
// this line then adjust the next character.
userbuf.setAddressOfNextRawChar(base);
if (originPrincipals)
JS_HoldPrincipals(originPrincipals);
JSContext *ncx = cx->asJSContext();
{
if (originPrincipals)
JS_HoldPrincipals(originPrincipals);
JSSourceHandler listener = cx->runtime()->debugHooks.sourceHandler;
void *listenerData = cx->runtime()->debugHooks.sourceHandlerData;
JSSourceHandler listener = ncx->runtime()->debugHooks.sourceHandler;
void *listenerData = ncx->runtime()->debugHooks.sourceHandlerData;
if (listener)
listener(options.filename, options.lineno, base, length, &listenerTSData, listenerData);
if (listener) {
void *listenerTSData;
listener(options.filename, options.lineno, base, length, &listenerTSData, listenerData);
}
}
/*
* This table holds all the token kinds that satisfy these properties:
@ -355,7 +359,7 @@ TokenStream::~TokenStream()
if (sourceMap)
js_free(sourceMap);
if (originPrincipals)
JS_DropPrincipals(cx->runtime(), originPrincipals);
JS_DropPrincipals(cx->asJSContext()->runtime(), originPrincipals);
}
/* Use the fastest available getc. */
@ -583,7 +587,7 @@ TokenStream::reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, uns
unsigned flags = JSREPORT_STRICT;
if (strictMode)
flags |= JSREPORT_ERROR;
else if (cx->hasExtraWarningsOption())
else if (options().extraWarningsOption)
flags |= JSREPORT_WARNING;
else
return true;
@ -649,11 +653,16 @@ TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigne
{
bool warning = JSREPORT_IS_WARNING(flags);
if (warning && cx->hasWErrorOption()) {
if (warning && options().werrorOption) {
flags &= ~JSREPORT_WARNING;
warning = false;
}
if (!this->cx->isJSContext())
return warning;
JSContext *cx = this->cx->asJSContext();
CompileError err(cx);
err.report.flags = flags;
@ -762,7 +771,7 @@ TokenStream::reportWarning(unsigned errorNumber, ...)
bool
TokenStream::reportStrictWarningErrorNumberVA(uint32_t offset, unsigned errorNumber, va_list args)
{
if (!cx->hasExtraWarningsOption())
if (!options().extraWarningsOption)
return true;
return reportCompileErrorNumberVA(offset, JSREPORT_STRICT|JSREPORT_WARNING, errorNumber, args);
@ -903,7 +912,7 @@ TokenStream::newToken(ptrdiff_t adjust)
}
JS_ALWAYS_INLINE JSAtom *
TokenStream::atomize(JSContext *cx, CharBuffer &cb)
TokenStream::atomize(ExclusiveContext *cx, CharBuffer &cb)
{
return AtomizeChars<CanGC>(cx, cb.begin(), cb.length());
}

View File

@ -359,12 +359,6 @@ struct CompileError {
void throwError();
};
inline bool
StrictModeFromContext(JSContext *cx)
{
return cx->hasOption(JSOPTION_STRICT_MODE);
}
// Ideally, tokenizing would be entirely independent of context. But the
// strict mode flag, which is in SharedContext, affects tokenizing, and
// TokenStream needs to see it.
@ -433,14 +427,13 @@ class MOZ_STACK_CLASS TokenStream
public:
typedef Vector<jschar, 32> CharBuffer;
TokenStream(JSContext *cx, const CompileOptions &options,
TokenStream(ExclusiveContext *cx, const CompileOptions &options,
const jschar *base, size_t length, StrictModeGetter *smg,
AutoKeepAtoms& keepAtoms);
~TokenStream();
/* Accessors. */
JSContext *getContext() const { return cx; }
bool onCurrentLine(const TokenPos &pos) const { return srcCoords.isOnThisLine(pos.end, lineno); }
const Token &currentToken() const { return tokens[cursor]; }
bool isCurrentTokenType(TokenKind type) const {
@ -454,8 +447,8 @@ class MOZ_STACK_CLASS TokenStream
const char *getFilename() const { return filename; }
unsigned getLineno() const { return lineno; }
unsigned getColumn() const { return userbuf.addressOfNextRawChar() - linebase - 1; }
JSVersion versionNumber() const { return VersionNumber(version); }
JSVersion versionWithFlags() const { return version; }
JSVersion versionNumber() const { return VersionNumber(options().version); }
JSVersion versionWithFlags() const { return options().version; }
bool hadError() const { return !!(flags & TSF_HAD_ERROR); }
bool isCurrentTokenEquality() const {
@ -505,7 +498,7 @@ class MOZ_STACK_CLASS TokenStream
bool strictMode() const { return strictModeGetter && strictModeGetter->strictMode(); }
void onError();
static JSAtom *atomize(JSContext *cx, CharBuffer &cb);
static JSAtom *atomize(ExclusiveContext *cx, CharBuffer &cb);
bool putIdentInTokenbuf(const jschar *identStart);
/*
@ -737,7 +730,7 @@ class MOZ_STACK_CLASS TokenStream
uint32_t lineNumToIndex(uint32_t lineNum) const { return lineNum - initialLineNum_; }
public:
SourceCoords(JSContext *cx, uint32_t ln);
SourceCoords(ExclusiveContext *cx, uint32_t ln);
void add(uint32_t lineNum, uint32_t lineStartOffset);
void fill(const SourceCoords &other);
@ -756,6 +749,18 @@ class MOZ_STACK_CLASS TokenStream
SourceCoords srcCoords;
JSAtomState &names() const {
return cx->names();
}
ExclusiveContext *context() const {
return cx;
}
const CompileOptions &options() const {
return options_;
}
private:
/*
* This is the low-level interface to the JS source code buffer. It just
@ -766,7 +771,7 @@ class MOZ_STACK_CLASS TokenStream
*/
class TokenBuf {
public:
TokenBuf(JSContext *cx, const jschar *buf, size_t length)
TokenBuf(ExclusiveContext *cx, const jschar *buf, size_t length)
: base_(buf), limit_(buf + length), ptr(buf),
skipBase(cx, &base_), skipLimit(cx, &limit_), skipPtr(cx, &ptr)
{ }
@ -891,6 +896,9 @@ class MOZ_STACK_CLASS TokenStream
void updateLineInfoForEOL();
void updateFlagsForEOL();
// Options used for parsing/tokenizing.
const CompileOptions &options_;
Token tokens[ntokens];/* circular token buffer */
unsigned cursor; /* index of last parsed token */
unsigned lookahead; /* count of lookahead tokens */
@ -901,13 +909,11 @@ class MOZ_STACK_CLASS TokenStream
TokenBuf userbuf; /* user input buffer */
const char *filename; /* input filename or null */
jschar *sourceMap; /* source map's filename or null */
void *listenerTSData;/* listener data for this TokenStream */
CharBuffer tokenbuf; /* current token string buffer */
int8_t oneCharTokens[128]; /* table of one-char tokens */
bool maybeEOL[256]; /* probabilistic EOL lookup table */
bool maybeStrSpecial[256];/* speeds up string scanning */
JSVersion version; /* (i.e. to identify keywords) */
JSContext *const cx;
ExclusiveContext *const cx;
JSPrincipals *const originPrincipals;
StrictModeGetter *strictModeGetter; /* used to test for strict mode */

View File

@ -572,16 +572,20 @@ AutoGCRooter::trace(JSTracer *trc)
/* static */ void
AutoGCRooter::traceAll(JSTracer *trc)
{
for (js::AutoGCRooter *gcr = trc->runtime->autoGCRooters; gcr; gcr = gcr->down)
gcr->trace(trc);
for (ContextIter cx(trc->runtime); !cx.done(); cx.next()) {
for (js::AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down)
gcr->trace(trc);
}
}
/* static */ void
AutoGCRooter::traceAllWrappers(JSTracer *trc)
{
for (js::AutoGCRooter *gcr = trc->runtime->autoGCRooters; gcr; gcr = gcr->down) {
if (gcr->tag_ == WRAPVECTOR || gcr->tag_ == WRAPPER)
gcr->trace(trc);
for (ContextIter cx(trc->runtime); !cx.done(); cx.next()) {
for (js::AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down) {
if (gcr->tag_ == WRAPVECTOR || gcr->tag_ == WRAPPER)
gcr->trace(trc);
}
}
}

View File

@ -1,5 +1,6 @@
#include "gdb-tests.h"
#include "jsatom.h"
#include "jscntxt.h"
// When JSGC_ANALYSIS is #defined, Rooted<JSFlatString*> needs the definition
// of JSFlatString in order to figure out its ThingRootKind

View File

@ -1452,7 +1452,7 @@ class MOZ_STACK_CLASS ModuleCompiler
for (unsigned i = 0; i < slowFunctions_.length(); i++) {
SlowFunction &func = slowFunctions_[i];
JSAutoByteString name;
if (!js_AtomToPrintableString(cx_, func.name, &name))
if (!AtomToPrintableString(cx_, func.name, &name))
return;
slowFuns.reset(JS_smprintf("%s%s:%u:%u (%ums)%s", slowFuns.get(),
name.ptr(), func.line, func.column, func.ms,

View File

@ -446,7 +446,7 @@ SendFunctionsToVTune(JSContext *cx, AsmJSModule &module)
return false;
JSAutoByteString bytes;
const char *method_name = js_AtomToPrintableString(cx, func.name, &bytes);
const char *method_name = AtomToPrintableString(cx, func.name, &bytes);
if (!method_name)
return false;

View File

@ -4447,7 +4447,7 @@ IonBuilder::createThisScriptedSingleton(HandleFunction target, MDefinition *call
// Generate an inline path to create a new |this| object with
// the given singleton prototype.
types::TypeObject *type = proto->getNewType(cx, &ObjectClass, target);
types::TypeObject *type = cx->getNewType(&ObjectClass, proto.get(), target);
if (!type)
return NULL;
if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(type)))

View File

@ -802,6 +802,12 @@ MacroAssembler::performOsr()
ret();
}
static void
ReportOverRecursed(JSContext *cx)
{
js_ReportOverRecursed(cx);
}
void
MacroAssembler::generateBailoutTail(Register scratch, Register bailoutInfo)
{
@ -823,7 +829,7 @@ MacroAssembler::generateBailoutTail(Register scratch, Register bailoutInfo)
loadJSContext(ReturnReg);
setupUnalignedABICall(1, scratch);
passABIArg(ReturnReg);
callWithABI(JS_FUNC_TO_DATA_PTR(void *, js_ReportOverRecursed));
callWithABI(JS_FUNC_TO_DATA_PTR(void *, ReportOverRecursed));
jump(&exception);
}

View File

@ -256,8 +256,8 @@ do {
} while(0)
static ParallelResult
ParCompareStrings(ForkJoinSlice *slice, HandleString str1,
HandleString str2, int32_t *res)
ParCompareStrings(ForkJoinSlice *slice, JSString *str1,
JSString *str2, int32_t *res)
{
if (!str1->isLinear())
return TP_RETRY_SEQUENTIALLY;
@ -283,9 +283,7 @@ ParCompareMaybeStrings(ForkJoinSlice *slice,
return TP_RETRY_SEQUENTIALLY;
if (!v2.isString())
return TP_RETRY_SEQUENTIALLY;
RootedString str1(slice->perThreadData, v1.toString());
RootedString str2(slice->perThreadData, v2.toString());
return ParCompareStrings(slice, str1, str2, res);
return ParCompareStrings(slice, v1.toString(), v2.toString(), res);
}
template<bool Equal>

View File

@ -13,11 +13,11 @@ using namespace js;
void *
TempAllocPolicy::onOutOfMemory(void *p, size_t nbytes)
{
return cx_->runtime()->onOutOfMemory(p, nbytes, cx_);
return static_cast<ThreadSafeContext *>(cx_)->onOutOfMemory(p, nbytes);
}
void
TempAllocPolicy::reportAllocOverflow() const
{
js_ReportAllocationOverflow(cx_);
js_ReportAllocationOverflow(static_cast<ThreadSafeContext *>(cx_));
}

View File

@ -13,6 +13,8 @@ struct JSContext;
namespace js {
class ContextFriendFields;
/*
* Allocation policies. These model the concept:
* - public copy constructor, assignment, destructor
@ -52,7 +54,7 @@ class SystemAllocPolicy
*/
class TempAllocPolicy
{
JSContext *const cx_;
ContextFriendFields *const cx_;
/*
* Non-inline helper to call JSRuntime::onOutOfMemory with minimal
@ -61,11 +63,8 @@ class TempAllocPolicy
JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes);
public:
TempAllocPolicy(JSContext *cx) : cx_(cx) {}
JSContext *context() const {
return cx_;
}
TempAllocPolicy(JSContext *cx) : cx_((ContextFriendFields *) cx) {} // :(
TempAllocPolicy(ContextFriendFields *cx) : cx_(cx) {}
void *malloc_(size_t bytes) {
void *p = js_malloc(bytes);

View File

@ -816,7 +816,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
analysisPurgeCallback(NULL),
analysisPurgeTriggerBytes(0),
gcMallocBytes(0),
autoGCRooters(NULL),
scriptAndCountsVector(NULL),
NaNValue(UndefinedValue()),
negativeInfinityValue(UndefinedValue()),
@ -5181,6 +5180,10 @@ JS::CompileOptions::CompileOptions(JSContext *cx, JSVersion version)
noScriptRval(cx->hasOption(JSOPTION_NO_SCRIPT_RVAL)),
selfHostingMode(false),
canLazilyParse(true),
strictOption(cx->hasOption(JSOPTION_STRICT_MODE)),
extraWarningsOption(cx->hasExtraWarningsOption()),
werrorOption(cx->hasWErrorOption()),
asmJSOption(cx->hasOption(JSOPTION_ASMJS)),
sourcePolicy(SAVE_SOURCE)
{
}
@ -5311,7 +5314,8 @@ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *objArg, const char *utf8, siz
{
CompileOptions options(cx);
options.setCompileAndGo(false);
Parser<frontend::FullParseHandler> parser(cx, options, chars, length,
Parser<frontend::FullParseHandler> parser(cx, &cx->tempLifoAlloc(),
options, chars, length,
/* foldConstants = */ true, NULL, NULL);
older = JS_SetErrorReporter(cx, NULL);
if (!parser.parse(obj) && parser.tokenStream.isUnexpectedEOF()) {
@ -7122,7 +7126,18 @@ JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
}
AutoGCRooter::AutoGCRooter(JSContext *cx, ptrdiff_t tag)
: down(cx->runtime()->autoGCRooters), tag_(tag), stackTop(&cx->runtime()->autoGCRooters)
: down(ContextFriendFields::get(cx)->autoGCRooters),
tag_(tag),
stackTop(&ContextFriendFields::get(cx)->autoGCRooters)
{
JS_ASSERT(this != *stackTop);
*stackTop = this;
}
AutoGCRooter::AutoGCRooter(ContextFriendFields *cx, ptrdiff_t tag)
: down(cx->autoGCRooters),
tag_(tag),
stackTop(&cx->autoGCRooters)
{
JS_ASSERT(this != *stackTop);
*stackTop = this;

View File

@ -54,6 +54,7 @@ class JS_PUBLIC_API(AutoCheckRequestDepth)
JSContext *cx;
public:
AutoCheckRequestDepth(JSContext *cx);
AutoCheckRequestDepth(js::ContextFriendFields *cx);
~AutoCheckRequestDepth();
};
@ -84,6 +85,7 @@ inline void AssertArgumentsAreSane(JSContext *cx, const Value &v) {
class JS_PUBLIC_API(AutoGCRooter) {
public:
AutoGCRooter(JSContext *cx, ptrdiff_t tag);
AutoGCRooter(js::ContextFriendFields *cx, ptrdiff_t tag);
~AutoGCRooter() {
JS_ASSERT(this == *stackTop);
@ -227,6 +229,13 @@ class AutoVectorRooter : protected AutoGCRooter
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
explicit AutoVectorRooter(js::ContextFriendFields *cx, ptrdiff_t tag
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, tag), vector(cx), vectorRoot(cx, &vector)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
typedef T ElementType;
size_t length() const { return vector.length(); }
@ -578,7 +587,14 @@ class AutoFunctionVector : public AutoVectorRooter<JSFunction *>
{
public:
explicit AutoFunctionVector(JSContext *cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoVectorRooter<JSFunction *>(cx, FUNVECTOR)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
explicit AutoFunctionVector(js::ContextFriendFields *cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoVectorRooter<JSFunction *>(cx, FUNVECTOR)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
@ -606,7 +622,8 @@ class AutoScriptVector : public AutoVectorRooter<JSScript *>
class JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter
{
public:
explicit CustomAutoRooter(JSContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
template <typename CX>
explicit CustomAutoRooter(CX *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, CUSTOM)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
@ -3938,6 +3955,10 @@ struct JS_PUBLIC_API(CompileOptions) {
bool noScriptRval;
bool selfHostingMode;
bool canLazilyParse;
bool strictOption;
bool extraWarningsOption;
bool werrorOption;
bool asmJSOption;
enum SourcePolicy {
NO_SOURCE,
LAZY_SOURCE,
@ -4469,6 +4490,8 @@ class JSAutoByteString
return mBytes;
}
char *encodeLatin1(js::ContextFriendFields *cx, JSString *str);
char *encodeUtf8(JSContext *cx, JSString *str) {
JS_ASSERT(!mBytes);
JS_ASSERT(cx);

View File

@ -423,7 +423,10 @@ js::CanonicalizeArrayLengthValue(JSContext *cx, HandleValue v, uint32_t *newLen)
if (d == *newLen)
return true;
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
if (!cx->isJSContext())
return false;
JS_ReportErrorNumber(cx->asJSContext(), js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
return false;
}
@ -461,14 +464,14 @@ js::ArraySetLength(JSContext *cx, Handle<ArrayObject*> arr, HandleId id, unsigne
return true;
if (setterIsStrict) {
return JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
return JS_ReportErrorFlagsAndNumber(cx->asJSContext(),
JSREPORT_ERROR, js_GetErrorMessage, NULL,
JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
}
return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
return JSObject::reportReadOnly(cx->asJSContext(), id, JSREPORT_STRICT | JSREPORT_WARNING);
}
/* Step 8. */
bool succeeded = true;
do {
@ -657,7 +660,8 @@ js::ArraySetLength(JSContext *cx, Handle<ArrayObject*> arr, HandleId id, unsigne
}
bool
js::WouldDefinePastNonwritableLength(JSContext *cx, HandleObject obj, uint32_t index, bool strict,
js::WouldDefinePastNonwritableLength(ExclusiveContext *cx,
HandleObject obj, uint32_t index, bool strict,
bool *definesPast)
{
if (!obj->is<ArrayObject>()) {
@ -678,13 +682,19 @@ js::WouldDefinePastNonwritableLength(JSContext *cx, HandleObject obj, uint32_t i
}
*definesPast = true;
if (!strict && !cx->hasExtraWarningsOption())
if (!cx->isJSContext())
return true;
JSContext *ncx = cx->asJSContext();
if (!strict && !ncx->hasExtraWarningsOption())
return true;
// Error in strict mode code or warn with strict option.
// XXX include the index and maybe array length in the error message
unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_STRICT | JSREPORT_WARNING);
return JS_ReportErrorFlagsAndNumber(cx, flags, js_GetErrorMessage, NULL,
return JS_ReportErrorFlagsAndNumber(ncx, flags, js_GetErrorMessage, NULL,
JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
}
@ -768,7 +778,7 @@ Class ArrayObject::class_ = {
};
static bool
AddLengthProperty(JSContext *cx, HandleObject obj)
AddLengthProperty(ExclusiveContext *cx, HandleObject obj)
{
/*
* Add the 'length' property for a newly created array,
@ -2883,7 +2893,7 @@ js_InitArrayClass(JSContext *cx, HandleObject obj)
if (!proto)
return NULL;
RootedTypeObject type(cx, proto->getNewType(cx, &ArrayObject::class_));
RootedTypeObject type(cx, cx->getNewType(&ArrayObject::class_, proto.get()));
if (!type)
return NULL;
@ -2941,7 +2951,7 @@ js_InitArrayClass(JSContext *cx, HandleObject obj)
*/
static inline bool
EnsureNewArrayElements(JSContext *cx, JSObject *obj, uint32_t length)
EnsureNewArrayElements(ExclusiveContext *cx, JSObject *obj, uint32_t length)
{
/*
* If ensureElements creates dynamically allocated slots, then having
@ -2959,81 +2969,84 @@ EnsureNewArrayElements(JSContext *cx, JSObject *obj, uint32_t length)
template<bool allocateCapacity>
static JS_ALWAYS_INLINE ArrayObject *
NewArray(JSContext *cx, uint32_t length, JSObject *protoArg, NewObjectKind newKind = GenericObject)
NewArray(ExclusiveContext *cxArg, uint32_t length,
JSObject *protoArg, NewObjectKind newKind = GenericObject)
{
gc::AllocKind allocKind = GuessArrayGCKind(length);
JS_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_));
allocKind = GetBackgroundAllocKind(allocKind);
NewObjectCache &cache = cx->runtime()->newObjectCache;
NewObjectCache::EntryIndex entry = -1;
if (newKind == GenericObject &&
!cx->compartment()->objectMetadataCallback &&
cache.lookupGlobal(&ArrayObject::class_, cx->global(), allocKind, &entry))
{
RootedObject obj(cx, cache.newObjectFromHit(cx, entry,
GetInitialHeap(newKind, &ArrayObject::class_)));
if (obj) {
/* Fixup the elements pointer and length, which may be incorrect. */
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
arr->setFixedElements();
ArrayObject::setLength(cx, arr, length);
if (allocateCapacity && !EnsureNewArrayElements(cx, arr, length))
return NULL;
return arr;
if (JSContext *cx = cxArg->maybeJSContext()) {
NewObjectCache &cache = cx->runtime()->newObjectCache;
if (newKind == GenericObject &&
!cx->compartment()->objectMetadataCallback &&
cache.lookupGlobal(&ArrayObject::class_, cx->global(), allocKind, &entry))
{
RootedObject obj(cx, cache.newObjectFromHit(cx, entry,
GetInitialHeap(newKind, &ArrayObject::class_)));
if (obj) {
/* Fixup the elements pointer and length, which may be incorrect. */
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
arr->setFixedElements();
ArrayObject::setLength(cx, arr, length);
if (allocateCapacity && !EnsureNewArrayElements(cx, arr, length))
return NULL;
return arr;
}
}
}
RootedObject proto(cx, protoArg);
RootedObject proto(cxArg, protoArg);
if (protoArg)
JS::PoisonPtr(&protoArg);
if (!proto && !FindProto(cx, &ArrayObject::class_, &proto))
if (!proto && !FindProto(cxArg, &ArrayObject::class_, &proto))
return NULL;
RootedTypeObject type(cx, proto->getNewType(cx, &ArrayObject::class_));
RootedTypeObject type(cxArg, cxArg->getNewType(&ArrayObject::class_, proto.get()));
if (!type)
return NULL;
JSObject *metadata = NULL;
if (!NewObjectMetadata(cx, &metadata))
if (!NewObjectMetadata(cxArg, &metadata))
return NULL;
/*
* Get a shape with zero fixed slots, regardless of the size class.
* See JSObject::createArray.
*/
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayObject::class_, TaggedProto(proto),
cx->global(), metadata, gc::FINALIZE_OBJECT0));
RootedShape shape(cxArg, EmptyShape::getInitialShape(cxArg, &ArrayObject::class_,
TaggedProto(proto), cxArg->global(),
metadata, gc::FINALIZE_OBJECT0));
if (!shape)
return NULL;
RootedObject obj(cx, JSObject::createArray(cx, allocKind,
GetInitialHeap(newKind, &ArrayObject::class_),
shape, type, length));
if (!obj)
Rooted<ArrayObject*> arr(cxArg, JSObject::createArray(cxArg, allocKind,
GetInitialHeap(newKind, &ArrayObject::class_),
shape, type, length));
if (!arr)
return NULL;
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (shape->isEmptyShape()) {
if (!AddLengthProperty(cx, arr))
if (!AddLengthProperty(cxArg, arr))
return NULL;
shape = arr->lastProperty();
EmptyShape::insertInitialShape(cx, shape, proto);
EmptyShape::insertInitialShape(cxArg, shape, proto);
}
if (newKind == SingletonObject && !JSObject::setSingletonType(cx, arr))
if (newKind == SingletonObject && !JSObject::setSingletonType(cxArg, arr))
return NULL;
if (entry != -1)
cache.fillGlobal(entry, &ArrayObject::class_, cx->global(), allocKind, arr);
if (entry != -1) {
cxArg->asJSContext()->runtime()->newObjectCache.fillGlobal(entry, &ArrayObject::class_,
cxArg->global(), allocKind, arr);
}
if (allocateCapacity && !EnsureNewArrayElements(cx, arr, length))
if (allocateCapacity && !EnsureNewArrayElements(cxArg, arr, length))
return NULL;
Probes::createObject(cx, arr);
Probes::createObject(cxArg, arr);
return arr;
}
@ -3045,14 +3058,14 @@ js::NewDenseEmptyArray(JSContext *cx, JSObject *proto /* = NULL */,
}
ArrayObject * JS_FASTCALL
js::NewDenseAllocatedArray(JSContext *cx, uint32_t length, JSObject *proto /* = NULL */,
js::NewDenseAllocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto /* = NULL */,
NewObjectKind newKind /* = GenericObject */)
{
return NewArray<true>(cx, length, proto, newKind);
}
ArrayObject * JS_FASTCALL
js::NewDenseUnallocatedArray(JSContext *cx, uint32_t length, JSObject *proto /* = NULL */,
js::NewDenseUnallocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto /* = NULL */,
NewObjectKind newKind /* = GenericObject */)
{
return NewArray<false>(cx, length, proto, newKind);

View File

@ -50,7 +50,7 @@ NewDenseEmptyArray(JSContext *cx, JSObject *proto = NULL,
/* Create a dense array with length and capacity == 'length', initialized length set to 0. */
extern ArrayObject * JS_FASTCALL
NewDenseAllocatedArray(JSContext *cx, uint32_t length, JSObject *proto = NULL,
NewDenseAllocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto = NULL,
NewObjectKind newKind = GenericObject);
/*
@ -58,7 +58,7 @@ NewDenseAllocatedArray(JSContext *cx, uint32_t length, JSObject *proto = NULL,
* contents. This is useful, e.g., when accepting length from the user.
*/
extern ArrayObject * JS_FASTCALL
NewDenseUnallocatedArray(JSContext *cx, uint32_t length, JSObject *proto = NULL,
NewDenseUnallocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto = NULL,
NewObjectKind newKind = GenericObject);
/* Create a dense array with a copy of the dense array elements in src. */
@ -76,7 +76,8 @@ NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, JSObjec
* increase the length of the array.
*/
extern bool
WouldDefinePastNonwritableLength(JSContext *cx, HandleObject obj, uint32_t index, bool strict,
WouldDefinePastNonwritableLength(ExclusiveContext *cx,
HandleObject obj, uint32_t index, bool strict,
bool *definesPast);
/*

View File

@ -37,9 +37,9 @@ using mozilla::ArrayLength;
using mozilla::RangedPtr;
const char *
js_AtomToPrintableString(JSContext *cx, JSAtom *atom, JSAutoByteString *bytes)
js::AtomToPrintableString(ExclusiveContext *cx, JSAtom *atom, JSAutoByteString *bytes)
{
return js_ValueToPrintable(cx, StringValue(atom), bytes);
return js_ValueToPrintable(cx->asJSContext(), StringValue(atom), bytes);
}
const char * const js::TypeStrings[] = {
@ -232,11 +232,11 @@ enum OwnCharsBehavior
*/
JS_ALWAYS_INLINE
static JSAtom *
AtomizeAndTakeOwnership(JSContext *cx, jschar *tbchars, size_t length, InternBehavior ib)
AtomizeAndTakeOwnership(ExclusiveContext *cx, jschar *tbchars, size_t length, InternBehavior ib)
{
JS_ASSERT(tbchars[length] == 0);
if (JSAtom *s = cx->runtime()->staticStrings.lookup(tbchars, length)) {
if (JSAtom *s = cx->staticStrings().lookup(tbchars, length)) {
js_free(tbchars);
return s;
}
@ -247,7 +247,7 @@ AtomizeAndTakeOwnership(JSContext *cx, jschar *tbchars, size_t length, InternBeh
* unchanged, we need to re-lookup the table position because a last-ditch
* GC will potentially free some table entries.
*/
AtomSet& atoms = cx->runtime()->atoms;
AtomSet& atoms = cx->atoms();
AtomSet::AddPtr p = atoms.lookupForAdd(AtomHasher::Lookup(tbchars, length));
SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
if (p) {
@ -269,7 +269,7 @@ AtomizeAndTakeOwnership(JSContext *cx, jschar *tbchars, size_t length, InternBeh
if (!atoms.relookupOrAdd(p, AtomHasher::Lookup(tbchars, length),
AtomStateEntry(atom, bool(ib)))) {
JS_ReportOutOfMemory(cx); /* SystemAllocPolicy does not report OOM. */
js_ReportOutOfMemory(cx); /* SystemAllocPolicy does not report OOM. */
return NULL;
}
@ -280,9 +280,9 @@ AtomizeAndTakeOwnership(JSContext *cx, jschar *tbchars, size_t length, InternBeh
template <AllowGC allowGC>
JS_ALWAYS_INLINE
static JSAtom *
AtomizeAndCopyChars(JSContext *cx, const jschar *tbchars, size_t length, InternBehavior ib)
AtomizeAndCopyChars(ExclusiveContext *cx, const jschar *tbchars, size_t length, InternBehavior ib)
{
if (JSAtom *s = cx->runtime()->staticStrings.lookup(tbchars, length))
if (JSAtom *s = cx->staticStrings().lookup(tbchars, length))
return s;
/*
@ -292,7 +292,7 @@ AtomizeAndCopyChars(JSContext *cx, const jschar *tbchars, size_t length, InternB
* GC will potentially free some table entries.
*/
AtomSet& atoms = cx->runtime()->atoms;
AtomSet& atoms = cx->atoms();
AtomSet::AddPtr p = atoms.lookupForAdd(AtomHasher::Lookup(tbchars, length));
SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
if (p) {
@ -311,7 +311,7 @@ AtomizeAndCopyChars(JSContext *cx, const jschar *tbchars, size_t length, InternB
if (!atoms.relookupOrAdd(p, AtomHasher::Lookup(tbchars, length),
AtomStateEntry(atom, bool(ib)))) {
JS_ReportOutOfMemory(cx); /* SystemAllocPolicy does not report OOM. */
js_ReportOutOfMemory(cx); /* SystemAllocPolicy does not report OOM. */
return NULL;
}
@ -320,7 +320,8 @@ AtomizeAndCopyChars(JSContext *cx, const jschar *tbchars, size_t length, InternB
template <AllowGC allowGC>
JSAtom *
js::AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib /* = js::DoNotInternAtom */)
js::AtomizeString(ExclusiveContext *cx, JSString *str,
js::InternBehavior ib /* = js::DoNotInternAtom */)
{
if (str->isAtom()) {
JSAtom &atom = str->asAtom();
@ -328,7 +329,7 @@ js::AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib /* = js::D
if (ib != InternAtom || js::StaticStrings::isStatic(&atom))
return &atom;
AtomSet::Ptr p = cx->runtime()->atoms.lookup(AtomHasher::Lookup(&atom));
AtomSet::Ptr p = cx->atoms().lookup(AtomHasher::Lookup(&atom));
JS_ASSERT(p); /* Non-static atom must exist in atom state set. */
JS_ASSERT(p->asPtr() == &atom);
JS_ASSERT(ib == InternAtom);
@ -336,7 +337,7 @@ js::AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib /* = js::D
return &atom;
}
const jschar *chars = str->getChars(cx);
const jschar *chars = str->getChars(cx->asJSContext());
if (!chars)
return NULL;
@ -346,7 +347,7 @@ js::AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib /* = js::D
if (!allowGC)
return NULL;
JSLinearString *linear = str->ensureLinear(cx);
JSLinearString *linear = str->ensureLinear(cx->asJSContext());
if (!linear)
return NULL;
@ -355,13 +356,13 @@ js::AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib /* = js::D
}
template JSAtom *
js::AtomizeString<CanGC>(JSContext *cx, JSString *str, js::InternBehavior ib);
js::AtomizeString<CanGC>(ExclusiveContext *cx, JSString *str, InternBehavior ib);
template JSAtom *
js::AtomizeString<NoGC>(JSContext *cx, JSString *str, js::InternBehavior ib);
js::AtomizeString<NoGC>(ExclusiveContext *cx, JSString *str, InternBehavior ib);
JSAtom *
js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib)
js::Atomize(ExclusiveContext *cx, const char *bytes, size_t length, InternBehavior ib)
{
CHECK_REQUEST(cx);
@ -379,7 +380,11 @@ js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib)
*/
jschar inflated[ATOMIZE_BUF_MAX];
size_t inflatedLength = ATOMIZE_BUF_MAX - 1;
InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength);
if (!InflateStringToBuffer(cx->maybeJSContext(),
bytes, length, inflated, &inflatedLength))
{
return NULL;
}
return AtomizeAndCopyChars<CanGC>(cx, inflated, inflatedLength, ib);
}
@ -391,7 +396,7 @@ js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib)
template <AllowGC allowGC>
JSAtom *
js::AtomizeChars(JSContext *cx, const jschar *chars, size_t length, InternBehavior ib)
js::AtomizeChars(ExclusiveContext *cx, const jschar *chars, size_t length, InternBehavior ib)
{
CHECK_REQUEST(cx);
@ -402,14 +407,16 @@ js::AtomizeChars(JSContext *cx, const jschar *chars, size_t length, InternBehavi
}
template JSAtom *
js::AtomizeChars<CanGC>(JSContext *cx, const jschar *chars, size_t length, InternBehavior ib);
js::AtomizeChars<CanGC>(ExclusiveContext *cx,
const jschar *chars, size_t length, InternBehavior ib);
template JSAtom *
js::AtomizeChars<NoGC>(JSContext *cx, const jschar *chars, size_t length, InternBehavior ib);
js::AtomizeChars<NoGC>(ExclusiveContext *cx,
const jschar *chars, size_t length, InternBehavior ib);
template <AllowGC allowGC>
bool
js::IndexToIdSlow(JSContext *cx, uint32_t index,
js::IndexToIdSlow(ExclusiveContext *cx, uint32_t index,
typename MaybeRooted<jsid, allowGC>::MutableHandleType idp)
{
JS_ASSERT(index > JSID_INT_MAX);
@ -427,14 +434,14 @@ js::IndexToIdSlow(JSContext *cx, uint32_t index,
}
template bool
js::IndexToIdSlow<CanGC>(JSContext *cx, uint32_t index, MutableHandleId idp);
js::IndexToIdSlow<CanGC>(ExclusiveContext *cx, uint32_t index, MutableHandleId idp);
template bool
js::IndexToIdSlow<NoGC>(JSContext *cx, uint32_t index, FakeMutableHandle<jsid> idp);
js::IndexToIdSlow<NoGC>(ExclusiveContext *cx, uint32_t index, FakeMutableHandle<jsid> idp);
template <AllowGC allowGC>
JSAtom *
js::ToAtom(JSContext *cx, typename MaybeRooted<Value, allowGC>::HandleType v)
js::ToAtom(ExclusiveContext *cx, typename MaybeRooted<Value, allowGC>::HandleType v)
{
if (!v.isString()) {
JSString *str = js::ToStringSlow<allowGC>(cx, v);
@ -453,10 +460,10 @@ js::ToAtom(JSContext *cx, typename MaybeRooted<Value, allowGC>::HandleType v)
}
template JSAtom *
js::ToAtom<CanGC>(JSContext *cx, HandleValue v);
js::ToAtom<CanGC>(ExclusiveContext *cx, HandleValue v);
template JSAtom *
js::ToAtom<NoGC>(JSContext *cx, Value v);
js::ToAtom<NoGC>(ExclusiveContext *cx, Value v);
template<XDRMode mode>
bool

View File

@ -45,16 +45,12 @@ struct JsidHasher
}
};
} /* namespace js */
/*
* Return a printable, lossless char[] representation of a string-type atom.
* The lifetime of the result matches the lifetime of bytes.
*/
extern const char *
js_AtomToPrintableString(JSContext *cx, JSAtom *atom, JSAutoByteString *bytes);
namespace js {
AtomToPrintableString(ExclusiveContext *cx, JSAtom *atom, JSAutoByteString *bytes);
/* Compute a hash function from chars/length. */
inline uint32_t
@ -215,21 +211,21 @@ enum InternBehavior
};
extern JSAtom *
Atomize(JSContext *cx, const char *bytes, size_t length,
Atomize(ExclusiveContext *cx, const char *bytes, size_t length,
js::InternBehavior ib = js::DoNotInternAtom);
template <AllowGC allowGC>
extern JSAtom *
AtomizeChars(JSContext *cx, const jschar *chars, size_t length,
AtomizeChars(ExclusiveContext *cx, const jschar *chars, size_t length,
js::InternBehavior ib = js::DoNotInternAtom);
template <AllowGC allowGC>
extern JSAtom *
AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib = js::DoNotInternAtom);
AtomizeString(ExclusiveContext *cx, JSString *str, js::InternBehavior ib = js::DoNotInternAtom);
template <AllowGC allowGC>
extern JSAtom *
ToAtom(JSContext *cx, typename MaybeRooted<Value, allowGC>::HandleType v);
ToAtom(ExclusiveContext *cx, typename MaybeRooted<Value, allowGC>::HandleType v);
template<XDRMode mode>
bool

View File

@ -107,11 +107,11 @@ BackfillIndexInCharBuffer(uint32_t index, mozilla::RangedPtr<T> end)
template <AllowGC allowGC>
bool
IndexToIdSlow(JSContext *cx, uint32_t index,
IndexToIdSlow(ExclusiveContext *cx, uint32_t index,
typename MaybeRooted<jsid, allowGC>::MutableHandleType idp);
inline bool
IndexToId(JSContext *cx, uint32_t index, MutableHandleId idp)
IndexToId(ExclusiveContext *cx, uint32_t index, MutableHandleId idp)
{
MaybeCheckStackRoots(cx);
@ -194,14 +194,14 @@ TypeName(JSType type, JSContext *cx)
}
inline Handle<PropertyName*>
ClassName(JSProtoKey key, JSContext *cx)
ClassName(JSProtoKey key, ExclusiveContext *cx)
{
JS_ASSERT(key < JSProto_LIMIT);
JS_STATIC_ASSERT(offsetof(JSAtomState, Null) +
JSProto_LIMIT * sizeof(FixedHeapPtr<PropertyName>) <=
sizeof(JSAtomState));
JS_STATIC_ASSERT(JSProto_Null == 0);
return (&cx->runtime()->atomState.Null)[key];
return (&cx->names().Null)[key];
}
} // namespace js

View File

@ -178,9 +178,9 @@ js_InitBooleanClass(JSContext *cx, HandleObject obj)
}
JSString *
js_BooleanToString(JSContext *cx, JSBool b)
js_BooleanToString(ExclusiveContext *cx, JSBool b)
{
return b ? cx->runtime()->atomState.true_ : cx->runtime()->atomState.false_;
return b ? cx->names().true_ : cx->names().false_;
}
JS_PUBLIC_API(bool)

View File

@ -16,7 +16,7 @@ extern JSObject *
js_InitBooleanClass(JSContext *cx, js::HandleObject obj);
extern JSString *
js_BooleanToString(JSContext *cx, JSBool b);
js_BooleanToString(js::ExclusiveContext *cx, JSBool b);
namespace js {

View File

@ -375,8 +375,12 @@ PopulateReportBlame(JSContext *cx, JSErrorReport *report)
* not occur, so GC must be avoided or suppressed.
*/
void
js_ReportOutOfMemory(JSContext *cx)
js_ReportOutOfMemory(ThreadSafeContext *cxArg)
{
if (!cxArg->isJSContext())
return;
JSContext *cx = cxArg->asJSContext();
cx->runtime()->hadOutOfMemory = true;
if (JS_IsRunning(cx)) {
@ -422,12 +426,20 @@ js_ReportOverRecursed(JSContext *maybecx)
}
void
js_ReportAllocationOverflow(JSContext *maybecx)
js_ReportOverRecursed(ThreadSafeContext *cx)
{
if (maybecx) {
AutoSuppressGC suppressGC(maybecx);
JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL, JSMSG_ALLOC_OVERFLOW);
}
js_ReportOverRecursed(cx->maybeJSContext());
}
void
js_ReportAllocationOverflow(ThreadSafeContext *cxArg)
{
if (!cxArg || !cxArg->isJSContext())
return;
JSContext *cx = cxArg->asJSContext();
AutoSuppressGC suppressGC(cx);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_ALLOC_OVERFLOW);
}
/*
@ -1025,19 +1037,6 @@ js::ThreadSafeContext::ThreadSafeContext(JSRuntime *rt, PerThreadData *pt, Conte
perThreadData(pt)
{ }
bool
ThreadSafeContext::isJSContext() const
{
return contextKind_ == Context_JS;
}
JSContext *
ThreadSafeContext::asJSContext()
{
JS_ASSERT(isJSContext());
return reinterpret_cast<JSContext *>(this);
}
bool
ThreadSafeContext::isForkJoinSlice() const
{
@ -1052,7 +1051,7 @@ ThreadSafeContext::asForkJoinSlice()
}
JSContext::JSContext(JSRuntime *rt)
: ThreadSafeContext(rt, &rt->mainThread, Context_JS),
: ExclusiveContext(rt, &rt->mainThread, Context_JS),
throwing(false),
exception(UndefinedValue()),
options_(0),
@ -1084,13 +1083,6 @@ JSContext::JSContext(JSRuntime *rt)
JS_ASSERT(static_cast<ContextFriendFields*>(this) ==
ContextFriendFields::get(this));
#ifdef JSGC_TRACK_EXACT_ROOTS
PodArrayZero(thingGCRooters);
#endif
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
skipGCRooters = NULL;
#endif
}
JSContext::~JSContext()
@ -1311,10 +1303,22 @@ JS::AutoCheckRequestDepth::AutoCheckRequestDepth(JSContext *cx)
cx->runtime()->checkRequestDepth++;
}
JS::AutoCheckRequestDepth::AutoCheckRequestDepth(ContextFriendFields *cxArg)
: cx(static_cast<ThreadSafeContext *>(cxArg)->maybeJSContext())
{
if (cx) {
JS_ASSERT(cx->runtime()->requestDepth || cx->runtime()->isHeapBusy());
cx->runtime()->assertValidThread();
cx->runtime()->checkRequestDepth++;
}
}
JS::AutoCheckRequestDepth::~AutoCheckRequestDepth()
{
JS_ASSERT(cx->runtime()->checkRequestDepth != 0);
cx->runtime()->checkRequestDepth--;
if (cx) {
JS_ASSERT(cx->runtime()->checkRequestDepth != 0);
cx->runtime()->checkRequestDepth--;
}
}
#endif

View File

@ -30,6 +30,17 @@
#pragma warning(disable:4355) /* Silence warning about "this" used in base member initializer list */
#endif
struct DtoaState;
extern void
js_ReportOutOfMemory(js::ThreadSafeContext *cx);
extern void
js_ReportAllocationOverflow(js::ThreadSafeContext *cx);
extern void
js_ReportOverRecursed(js::ThreadSafeContext *cx);
namespace js {
struct CallsiteCloneKey {
@ -98,29 +109,44 @@ TraceCycleDetectionSet(JSTracer *trc, ObjectSet &set);
struct AutoResolving;
class ForkJoinSlice;
class RegExpCompartment;
class DtoaCache;
/*
* ThreadSafeContext is the base class for both JSContext, the "normal"
* sequential context, and ForkJoinSlice, the per-thread parallel context used
* in PJS.
* Execution Context Overview:
*
* When cast to a ThreadSafeContext, the only usable operations are casting
* back to the context from which it came, and generic allocation
* operations. These generic versions branch internally based on whether the
* underneath context is really a JSContext or a ForkJoinSlice, and are in
* general more expensive than using the context directly.
* Several different structures may be used to provide a context for operations
* on the VM. Each context is thread local, but varies in what data it can
* access and what other threads may be running.
*
* Thus, ThreadSafeContext should only be used for VM functions that may be
* called in both sequential and parallel execution. The most likely class of
* VM functions that do these are those that allocate commonly used data
* structures, such as concatenating strings and extending elements.
* - ThreadSafeContext is used by threads operating in one compartment which
* may run in parallel with other threads operating on the same or other
* compartments.
*
* - ExclusiveContext is used by threads operating in one compartment, where
* other threads may operate in other compartments, but *not* the one which
* the ExclusiveContext is in. A thread with an ExclusiveContext may enter the
* atoms compartment and atomize strings, in which case a lock is used.
*
* - JSContext is used only by the runtime's main thread. The context may
* operate in any compartment which is not locked by an ExclusiveContext or
* ThreadSafeContext, and will only run in parallel with threads using such
* contexts.
*
* An ExclusiveContext coerces to a ThreadSafeContext, and a JSContext coerces
* to an ExclusiveContext or ThreadSafeContext.
*
* Contexts which are a ThreadSafeContext but not an ExclusiveContext are used
* to represent a ForkJoinSlice, the per-thread parallel context used in PJS.
*/
struct ThreadSafeContext : js::ContextFriendFields,
struct ThreadSafeContext : ContextFriendFields,
public MallocProvider<ThreadSafeContext>
{
public:
enum ContextKind {
Context_JS,
Context_Exclusive,
Context_ForkJoin
};
@ -130,14 +156,46 @@ struct ThreadSafeContext : js::ContextFriendFields,
public:
PerThreadData *perThreadData;
explicit ThreadSafeContext(JSRuntime *rt, PerThreadData *pt, ContextKind kind);
ThreadSafeContext(JSRuntime *rt, PerThreadData *pt, ContextKind kind);
bool isJSContext() const;
JSContext *asJSContext();
bool isJSContext() const {
return contextKind_ == Context_JS;
}
JSContext *maybeJSContext() const {
if (isJSContext())
return (JSContext *) this;
return NULL;
}
JSContext *asJSContext() const {
// Note: there is no way to perform an unchecked coercion from a
// ThreadSafeContext to a JSContext. This ensures that trying to use
// the context as a JSContext off the main thread will NULL crash
// rather than race.
JS_ASSERT(isJSContext());
return maybeJSContext();
}
bool isExclusiveContext() const {
return contextKind_ == Context_JS || contextKind_ == Context_Exclusive;
}
ExclusiveContext *maybeExclusiveContext() const {
if (isExclusiveContext())
return (ExclusiveContext *) this;
return NULL;
}
ExclusiveContext *asExclusiveContext() const {
JS_ASSERT(isExclusiveContext());
return maybeExclusiveContext();
}
bool isForkJoinSlice() const;
ForkJoinSlice *asForkJoinSlice();
// The generational GC nursery may only be used on the main thread.
#ifdef JSGC_GENERATIONAL
inline bool hasNursery() const {
return isJSContext();
@ -149,20 +207,16 @@ struct ThreadSafeContext : js::ContextFriendFields,
}
#endif
/* Cut outs for string operations. */
StaticStrings &staticStrings() { return runtime_->staticStrings; }
JSAtomState &names() { return runtime_->atomState; }
/*
* Allocator used when allocating GCThings on this context. If we are a
* JSContext, this is the Zone allocator of the JSContext's zone. If we
* are the per-thread data of a ForkJoinSlice, this is a per-thread
* allocator.
* JSContext, this is the Zone allocator of the JSContext's zone.
* Otherwise, this is a per-thread allocator.
*
* This does not live in PerThreadData because the notion of an allocator
* is only per-thread in PJS. The runtime (and the main thread) can have
* more than one zone, each with its own allocator, and it's up to the
* context to specify what compartment and zone we are operating in.
* is only per-thread when off the main thread. The runtime (and the main
* thread) can have more than one zone, each with its own allocator, and
* it's up to the context to specify what compartment and zone we are
* operating in.
*/
protected:
Allocator *allocator_;
@ -172,39 +226,106 @@ struct ThreadSafeContext : js::ContextFriendFields,
inline Allocator *const allocator();
/* GC support. */
AllowGC allowGC() const {
switch (contextKind_) {
case Context_JS:
return CanGC;
case Context_ForkJoin:
return NoGC;
default:
/* Silence warnings. */
MOZ_ASSUME_UNREACHABLE("Bad context kind");
}
}
// Allocations can only trigger GC when running on the main thread.
inline AllowGC allowGC() const { return isJSContext() ? CanGC : NoGC; }
template <typename T>
bool isInsideCurrentZone(T thing) const {
return thing->isInsideZone(zone_);
}
void *onOutOfMemory(void *p, size_t nbytes) {
return runtime_->onOutOfMemory(p, nbytes, isJSContext() ? asJSContext() : NULL);
template <typename T>
inline bool isInsideCurrentCompartment(T thing) const {
return thing->compartment() == compartment_;
}
void *onOutOfMemory(void *p, size_t nbytes) {
return runtime_->onOutOfMemory(p, nbytes, maybeJSContext());
}
inline void updateMallocCounter(size_t nbytes) {
/* Note: this is racy. */
// Note: this is racy.
runtime_->updateMallocCounter(zone_, nbytes);
}
void reportAllocationOverflow() {
js_ReportAllocationOverflow(isJSContext() ? asJSContext() : NULL);
js_ReportAllocationOverflow(this);
}
// Builtin atoms are immutable and may be accessed freely from any thread.
JSAtomState &names() { return runtime_->atomState; }
StaticStrings &staticStrings() { return runtime_->staticStrings; }
PropertyName *emptyString() { return runtime_->emptyString; }
// GCs cannot happen while non-main threads are running.
uint64_t gcNumber() { return runtime_->gcNumber; }
bool isHeapBusy() { return runtime_->isHeapBusy(); }
// Thread local data that may be accessed freely.
DtoaState *dtoaState() {
return perThreadData->dtoaState;
}
};
class ExclusiveContext : public ThreadSafeContext
{
friend class gc::ArenaLists;
friend class CompartmentChecker;
friend class AutoEnterAtomsCompartment;
friend struct StackBaseShape;
friend void JSScript::initCompartmentAndPrincipals(ExclusiveContext *cx,
const JS::CompileOptions &options);
inline void privateSetCompartment(JSCompartment *comp);
public:
ExclusiveContext(JSRuntime *rt, PerThreadData *pt, ContextKind kind)
: ThreadSafeContext(rt, pt, kind)
{}
inline bool typeInferenceEnabled() const;
// Per compartment data that can be accessed freely from an ExclusiveContext.
inline RegExpCompartment &regExps();
inline RegExpStatics *regExpStatics();
inline PropertyTree &propertyTree();
inline BaseShapeSet &baseShapes();
inline InitialShapeSet &initialShapes();
inline DtoaCache &dtoaCache();
types::TypeObject *getNewType(Class *clasp, TaggedProto proto, JSFunction *fun = NULL);
// Current global. This is only safe to use within the scope of the
// AutoCompartment from which it's called.
inline js::Handle<js::GlobalObject*> global() const;
// Methods to access runtime wide data that must be protected by locks.
frontend::ParseMapPool &parseMapPool() {
runtime_->assertValidThread();
return runtime_->parseMapPool;
}
AtomSet &atoms() {
runtime_->assertValidThread();
return runtime_->atoms;
}
ScriptDataTable &scriptDataTable() {
runtime_->assertValidThread();
return runtime_->scriptDataTable;
}
};
inline void
MaybeCheckStackRoots(ExclusiveContext *cx)
{
MaybeCheckStackRoots(cx->maybeJSContext());
}
} /* namespace js */
struct JSContext : js::ThreadSafeContext,
struct JSContext : public js::ExclusiveContext,
public mozilla::LinkedListElement<JSContext>
{
explicit JSContext(JSRuntime *rt);
@ -294,12 +415,6 @@ struct JSContext : js::ThreadSafeContext,
inline void setDefaultCompartmentObjectIfUnset(JSObject *obj);
JSObject *maybeDefaultCompartmentObject() const { return defaultCompartmentObject_; }
/*
* Current global. This is only safe to use within the scope of the
* AutoCompartment from which it's called.
*/
inline js::Handle<js::GlobalObject*> global() const;
/* Wrap cx->exception for the current compartment. */
void wrapPendingException();
@ -316,8 +431,6 @@ struct JSContext : js::ThreadSafeContext,
void *data;
void *data2;
inline js::RegExpStatics *regExpStatics();
public:
/*
@ -349,8 +462,6 @@ struct JSContext : js::ThreadSafeContext,
inline js::LifoAlloc &analysisLifoAlloc();
inline js::LifoAlloc &typeLifoAlloc();
inline js::PropertyTree &propertyTree();
#ifdef JS_THREADSAFE
unsigned outstandingRequests;/* number of JS_BeginRequest calls
without the corresponding
@ -365,8 +476,6 @@ struct JSContext : js::ThreadSafeContext,
bool jitIsBroken;
inline bool typeInferenceEnabled() const;
void updateJITEnabled();
/* Whether this context has JS frames on the stack. */
@ -604,13 +713,13 @@ extern bool
js_ReportErrorNumberUCArray(JSContext *cx, unsigned flags, JSErrorCallback callback,
void *userRef, const unsigned errorNumber,
const jschar **args);
#endif
extern JSBool
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
void *userRef, const unsigned errorNumber,
char **message, JSErrorReport *reportp,
js::ErrorArgumentsType argumentsType, va_list ap);
#endif
namespace js {

View File

@ -30,12 +30,12 @@ namespace js {
#ifdef JS_CRASH_DIAGNOSTICS
class CompartmentChecker
{
JSContext *context;
ExclusiveContext *context;
JSCompartment *compartment;
public:
explicit CompartmentChecker(JSContext *cx)
: context(cx), compartment(cx->compartment())
explicit CompartmentChecker(ExclusiveContext *cx)
: context(cx), compartment(cx->compartment_)
{}
/*
@ -61,7 +61,7 @@ class CompartmentChecker
}
void check(JSCompartment *c) {
if (c && c != context->runtime()->atomsCompartment) {
if (c && c != compartment->rt->atomsCompartment) {
if (!compartment)
compartment = c;
else if (c != compartment)
@ -140,13 +140,12 @@ class CompartmentChecker
* depends on other objects not having been swept yet.
*/
#define START_ASSERT_SAME_COMPARTMENT() \
JS_ASSERT(cx->compartment()->zone() == cx->zone()); \
if (cx->runtime()->isHeapBusy()) \
if (cx->isHeapBusy()) \
return; \
CompartmentChecker c(cx)
template <class T1> inline void
assertSameCompartment(JSContext *cx, const T1 &t1)
assertSameCompartment(ExclusiveContext *cx, const T1 &t1)
{
#ifdef JS_CRASH_DIAGNOSTICS
START_ASSERT_SAME_COMPARTMENT();
@ -155,7 +154,7 @@ assertSameCompartment(JSContext *cx, const T1 &t1)
}
template <class T1> inline void
assertSameCompartmentDebugOnly(JSContext *cx, const T1 &t1)
assertSameCompartmentDebugOnly(ExclusiveContext *cx, const T1 &t1)
{
#ifdef DEBUG
START_ASSERT_SAME_COMPARTMENT();
@ -164,7 +163,7 @@ assertSameCompartmentDebugOnly(JSContext *cx, const T1 &t1)
}
template <class T1, class T2> inline void
assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2)
assertSameCompartment(ExclusiveContext *cx, const T1 &t1, const T2 &t2)
{
#ifdef JS_CRASH_DIAGNOSTICS
START_ASSERT_SAME_COMPARTMENT();
@ -174,7 +173,7 @@ assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2)
}
template <class T1, class T2, class T3> inline void
assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2, const T3 &t3)
assertSameCompartment(ExclusiveContext *cx, const T1 &t1, const T2 &t2, const T3 &t3)
{
#ifdef JS_CRASH_DIAGNOSTICS
START_ASSERT_SAME_COMPARTMENT();
@ -185,7 +184,8 @@ assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2, const T3 &t3)
}
template <class T1, class T2, class T3, class T4> inline void
assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4)
assertSameCompartment(ExclusiveContext *cx,
const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4)
{
#ifdef JS_CRASH_DIAGNOSTICS
START_ASSERT_SAME_COMPARTMENT();
@ -197,7 +197,8 @@ assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2, const T3 &t3, c
}
template <class T1, class T2, class T3, class T4, class T5> inline void
assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5)
assertSameCompartment(ExclusiveContext *cx,
const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5)
{
#ifdef JS_CRASH_DIAGNOSTICS
START_ASSERT_SAME_COMPARTMENT();
@ -338,6 +339,42 @@ CallSetter(JSContext *cx, HandleObject obj, HandleId id, StrictPropertyOp op, un
return CallJSPropertyOpSetter(cx, op, obj, nid, strict, vp);
}
inline uintptr_t
GetNativeStackLimit(ExclusiveContext *cx)
{
return GetNativeStackLimit(cx->asJSContext()->runtime());
}
inline RegExpCompartment &
ExclusiveContext::regExps()
{
return compartment_->regExps;
}
inline PropertyTree&
ExclusiveContext::propertyTree()
{
return compartment_->propertyTree;
}
inline BaseShapeSet &
ExclusiveContext::baseShapes()
{
return compartment_->baseShapes;
}
inline InitialShapeSet &
ExclusiveContext::initialShapes()
{
return compartment_->initialShapes;
}
inline DtoaCache &
ExclusiveContext::dtoaCache()
{
return compartment_->dtoaCache;
}
} /* namespace js */
inline js::LifoAlloc &
@ -360,12 +397,6 @@ JSContext::setPendingException(js::Value v) {
js::assertSameCompartment(this, v);
}
inline js::PropertyTree&
JSContext::propertyTree()
{
return compartment()->propertyTree;
}
inline void
JSContext::setDefaultCompartmentObject(JSObject *obj)
{
@ -435,6 +466,18 @@ JSContext::setCompartment(JSCompartment *comp)
allocator_ = zone_ ? &zone_->allocator : NULL;
}
inline void
js::ExclusiveContext::privateSetCompartment(JSCompartment *comp)
{
if (isJSContext()) {
asJSContext()->setCompartment(comp);
} else {
compartment_ = comp;
if (zone_ != comp->zone())
MOZ_CRASH();
}
}
inline JSScript *
JSContext::currentScript(jsbytecode **ppc,
MaybeAllowCrossCompartment allowCrossCompartment) const

View File

@ -135,6 +135,7 @@ struct JSCompartment
private:
friend struct JSRuntime;
friend struct JSContext;
friend class js::ExclusiveContext;
js::ReadBarriered<js::GlobalObject> global_;
unsigned enterCompartmentDepth;
@ -225,9 +226,6 @@ struct JSCompartment
js::types::TypeObjectSet lazyTypeObjects;
void sweepNewTypeObjectTable(js::types::TypeObjectSet &table);
js::types::TypeObject *getNewType(JSContext *cx, js::Class *clasp, js::TaggedProto proto,
JSFunction *fun = NULL);
js::types::TypeObject *getLazyType(JSContext *cx, js::Class *clasp, js::TaggedProto proto);
/*
@ -411,14 +409,20 @@ class js::AutoDebugModeGC
}
};
namespace js {
inline bool
JSContext::typeInferenceEnabled() const
ExclusiveContext::typeInferenceEnabled() const
{
return compartment()->zone()->types.inferenceEnabled;
// Type inference cannot be enabled in compartments which are accessed off
// the main thread by an ExclusiveContext. TI data is stored in per-zone
// allocators which could otherwise race with main thread operations.
JS_ASSERT_IF(!isJSContext(), !compartment_->zone()->types.inferenceEnabled);
return compartment_->zone()->types.inferenceEnabled;
}
inline js::Handle<js::GlobalObject*>
JSContext::global() const
ExclusiveContext::global() const
{
/*
* It's safe to use |unsafeGet()| here because any compartment that is
@ -426,11 +430,9 @@ JSContext::global() const
* barrier on it. Once the compartment is popped, the handle is no longer
* safe to use.
*/
return js::Handle<js::GlobalObject*>::fromMarkedLocation(compartment()->global_.unsafeGet());
return Handle<GlobalObject*>::fromMarkedLocation(compartment_->global_.unsafeGet());
}
namespace js {
class AssertCompartmentUnchanged
{
public:

View File

@ -41,7 +41,7 @@ js::AutoCompartment::~AutoCompartment()
namespace js {
/*
* Entering the atoms comaprtment is not possible with the AutoCompartment
* Entering the atoms compartment is not possible with AutoCompartment
* since the atoms compartment does not have a global.
*
* Note: since most of the VM assumes that cx->global is non-null, only a
@ -50,19 +50,19 @@ namespace js {
*/
class AutoEnterAtomsCompartment
{
JSContext *cx;
ExclusiveContext *cx;
JSCompartment *oldCompartment;
public:
AutoEnterAtomsCompartment(JSContext *cx)
AutoEnterAtomsCompartment(ExclusiveContext *cx)
: cx(cx),
oldCompartment(cx->compartment())
oldCompartment(cx->compartment_)
{
cx->setCompartment(cx->runtime()->atomsCompartment);
cx->privateSetCompartment(cx->runtime_->atomsCompartment);
}
~AutoEnterAtomsCompartment()
{
cx->setCompartment(oldCompartment);
cx->privateSetCompartment(oldCompartment);
}
};

View File

@ -44,6 +44,7 @@
#include "vm/StringBuffer.h"
#include "jsobjinlines.h"
#include "jsstrinlines.h"
using namespace js;
using namespace js::types;

View File

@ -30,6 +30,7 @@
#include "jsfuninlines.h"
#include "jsobjinlines.h"
#include "jsstrinlines.h"
using namespace js;
using namespace js::gc;

View File

@ -1128,11 +1128,15 @@ js_ReportIsNotFunction(JSContext *cx, const JS::Value& v)
return ReportIsNotFunction(cx, v);
}
#if defined(DEBUG) && defined(JS_THREADSAFE)
#ifdef DEBUG
JS_PUBLIC_API(bool)
js::IsInRequest(JSContext *cx)
{
#ifdef JS_THREADSAFE
return !!cx->runtime()->requestDepth;
#else
return true;
#endif
}
#endif

View File

@ -619,6 +619,12 @@ GetNativeStackLimit(const JSRuntime *rt)
return PerThreadDataFriendFields::getMainThread(rt)->nativeStackLimit;
}
inline uintptr_t
GetNativeStackLimit(JSContext *cx)
{
return GetNativeStackLimit(GetRuntime(cx));
}
/*
* These macros report a stack overflow and run |onerror| if we are close to
* using up the C stack. The JS_CHECK_CHROME_RECURSION variant gives us a little
@ -628,7 +634,7 @@ GetNativeStackLimit(const JSRuntime *rt)
#define JS_CHECK_RECURSION(cx, onerror) \
JS_BEGIN_MACRO \
int stackDummy_; \
if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(js::GetRuntime(cx)), &stackDummy_)) { \
if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), &stackDummy_)) { \
js_ReportOverRecursed(cx); \
onerror; \
} \
@ -637,7 +643,7 @@ GetNativeStackLimit(const JSRuntime *rt)
#define JS_CHECK_RECURSION_WITH_EXTRA_DONT_REPORT(cx, extra, onerror) \
JS_BEGIN_MACRO \
uint8_t stackDummy_; \
if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(js::GetRuntime(cx)), \
if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), \
&stackDummy_ - (extra))) \
{ \
onerror; \
@ -647,7 +653,7 @@ GetNativeStackLimit(const JSRuntime *rt)
#define JS_CHECK_CHROME_RECURSION(cx, onerror) \
JS_BEGIN_MACRO \
int stackDummy_; \
if (!JS_CHECK_STACK_SIZE_WITH_TOLERANCE(js::GetNativeStackLimit(js::GetRuntime(cx)), \
if (!JS_CHECK_STACK_SIZE_WITH_TOLERANCE(js::GetNativeStackLimit(cx), \
&stackDummy_, \
1024 * sizeof(size_t))) \
{ \

View File

@ -1534,7 +1534,7 @@ JSFunction::isBuiltinFunctionConstructor()
}
JSFunction *
js::NewFunction(JSContext *cx, HandleObject funobjArg, Native native, unsigned nargs,
js::NewFunction(ExclusiveContext *cx, HandleObject funobjArg, Native native, unsigned nargs,
JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
gc::AllocKind allocKind /* = JSFunction::FinalizeKind */,
NewObjectKind newKind /* = GenericObject */)

View File

@ -356,7 +356,7 @@ class JSFunction : public JSObject
inline const js::Value &getExtendedSlot(size_t which) const;
/* Constructs a new type for the function if necessary. */
static bool setTypeForScriptedFunction(JSContext *cx, js::HandleFunction fun,
static bool setTypeForScriptedFunction(js::ExclusiveContext *cx, js::HandleFunction fun,
bool singleton = false);
/* GC support. */
@ -386,7 +386,7 @@ extern JSBool
Function(JSContext *cx, unsigned argc, Value *vp);
extern JSFunction *
NewFunction(JSContext *cx, HandleObject funobj, JSNative native, unsigned nargs,
NewFunction(ExclusiveContext *cx, HandleObject funobj, JSNative native, unsigned nargs,
JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
gc::AllocKind allocKind = JSFunction::FinalizeKind,
NewObjectKind newKind = GenericObject);

View File

@ -393,7 +393,7 @@ TryNewNurseryGCThing(ThreadSafeContext *tcx, size_t thingSize)
*/
template <typename T, AllowGC allowGC>
inline T *
NewGCThing(js::ThreadSafeContext *tcx, AllocKind kind, size_t thingSize, InitialHeap heap)
NewGCThing(ThreadSafeContext *tcx, AllocKind kind, size_t thingSize, InitialHeap heap)
{
JS_ASSERT(thingSize == js::gc::Arena::thingSize(kind));
@ -418,7 +418,7 @@ NewGCThing(js::ThreadSafeContext *tcx, AllocKind kind, size_t thingSize, Initial
MaybeCheckStackRoots(cx);
}
#if defined(JSGC_GENERATIONAL)
#ifdef JSGC_GENERATIONAL
if (tcx->hasNursery() && ShouldNurseryAllocate(tcx->nursery(), kind, heap)) {
T *t = TryNewNurseryGCThing<T, allowGC>(tcx, thingSize);
if (t)

View File

@ -2338,9 +2338,9 @@ TypeZone::init(JSContext *cx)
}
TypeObject *
TypeCompartment::newTypeObject(JSContext *cx, Class *clasp, Handle<TaggedProto> proto, bool unknown)
TypeCompartment::newTypeObject(ExclusiveContext *cx, Class *clasp, Handle<TaggedProto> proto, bool unknown)
{
JS_ASSERT_IF(proto.isObject(), cx->compartment() == proto.toObject()->compartment());
JS_ASSERT_IF(proto.isObject(), cx->isInsideCurrentCompartment(proto.toObject()));
TypeObject *object = gc::NewGCThing<TypeObject, CanGC>(cx, gc::FINALIZE_TYPE_OBJECT,
sizeof(TypeObject), gc::TenuredHeap);
@ -5879,11 +5879,14 @@ JSScript::makeAnalysis(JSContext *cx)
}
/* static */ bool
JSFunction::setTypeForScriptedFunction(JSContext *cx, HandleFunction fun, bool singleton /* = false */)
JSFunction::setTypeForScriptedFunction(ExclusiveContext *cxArg, HandleFunction fun,
bool singleton /* = false */)
{
if (!cx->typeInferenceEnabled())
if (!cxArg->typeInferenceEnabled())
return true;
JSContext *cx = cxArg->asJSContext();
if (singleton) {
if (!setSingletonType(cx, fun))
return false;
@ -5954,7 +5957,7 @@ JSObject::splicePrototype(JSContext *cx, Class *clasp, Handle<TaggedProto> proto
}
if (!cx->typeInferenceEnabled()) {
TypeObject *type = cx->compartment()->getNewType(cx, clasp, proto);
TypeObject *type = cx->getNewType(clasp, proto);
if (!type)
return false;
self->type_ = type;
@ -6092,10 +6095,12 @@ JSObject::setNewTypeUnknown(JSContext *cx, Class *clasp, HandleObject obj)
}
TypeObject *
JSCompartment::getNewType(JSContext *cx, Class *clasp, TaggedProto proto_, JSFunction *fun_)
ExclusiveContext::getNewType(Class *clasp, TaggedProto proto_, JSFunction *fun_)
{
JS_ASSERT_IF(fun_, proto_.isObject());
JS_ASSERT_IF(proto_.isObject(), cx->compartment() == proto_.toObject()->compartment());
JS_ASSERT_IF(proto_.isObject(), isInsideCurrentCompartment(proto_.toObject()));
TypeObjectSet &newTypeObjects = compartment_->newTypeObjects;
if (!newTypeObjects.initialized() && !newTypeObjects.init())
return NULL;
@ -6116,15 +6121,15 @@ JSCompartment::getNewType(JSContext *cx, Class *clasp, TaggedProto proto_, JSFun
* 'prototype' property of some scripted function.
*/
if (type->newScript && type->newScript->fun != fun_)
type->clearNewScript(cx);
type->clearNewScript(asJSContext());
return type;
}
Rooted<TaggedProto> proto(cx, proto_);
RootedFunction fun(cx, fun_);
Rooted<TaggedProto> proto(this, proto_);
RootedFunction fun(this, fun_);
if (proto.isObject() && !proto.toObject()->setDelegate(cx))
if (proto.isObject() && !proto.toObject()->setDelegate(this))
return NULL;
bool markUnknown =
@ -6132,16 +6137,17 @@ JSCompartment::getNewType(JSContext *cx, Class *clasp, TaggedProto proto_, JSFun
? proto.toObject()->lastProperty()->hasObjectFlag(BaseShape::NEW_TYPE_UNKNOWN)
: true;
RootedTypeObject type(cx, types.newTypeObject(cx, clasp, proto, markUnknown));
RootedTypeObject type(this, compartment_->types.newTypeObject(this, clasp, proto, markUnknown));
if (!type)
return NULL;
if (!newTypeObjects.relookupOrAdd(p, TypeObjectSet::Lookup(clasp, proto), type.get()))
return NULL;
if (!cx->typeInferenceEnabled())
if (!typeInferenceEnabled())
return type;
JSContext *cx = asJSContext();
AutoEnterAnalysis enter(cx);
/*
@ -6182,12 +6188,6 @@ JSCompartment::getNewType(JSContext *cx, Class *clasp, TaggedProto proto_, JSFun
return type;
}
TypeObject *
JSObject::getNewType(JSContext *cx, Class *clasp, JSFunction *fun)
{
return cx->compartment()->getNewType(cx, clasp, this, fun);
}
TypeObject *
JSCompartment::getLazyType(JSContext *cx, Class *clasp, TaggedProto proto)
{

View File

@ -1412,7 +1412,7 @@ struct TypeCompartment
* or JSProto_Object to indicate a type whose class is unknown (not just
* js_ObjectClass).
*/
TypeObject *newTypeObject(JSContext *cx, Class *clasp, Handle<TaggedProto> proto,
TypeObject *newTypeObject(ExclusiveContext *cx, Class *clasp, Handle<TaggedProto> proto,
bool unknown = false);
/* Get or make an object for an allocation site, and add to the allocation site table. */

View File

@ -509,7 +509,7 @@ GetTypeNewObject(JSContext *cx, JSProtoKey key)
RootedObject proto(cx);
if (!js_GetClassPrototype(cx, key, &proto))
return NULL;
return proto->getNewType(cx, GetClassForProtoKey(key));
return cx->getNewType(GetClassForProtoKey(key), proto.get());
}
/* Get a type object for the immediate allocation site within a native. */
@ -556,12 +556,12 @@ TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
}
inline bool
TrackPropertyTypes(JSContext *cx, JSObject *obj, jsid id)
TrackPropertyTypes(ExclusiveContext *cx, JSObject *obj, jsid id)
{
if (!cx->typeInferenceEnabled() || obj->hasLazyType() || obj->type()->unknownProperties())
return false;
if (obj->hasSingletonType() && !obj->type()->maybeGetProperty(id, cx))
if (obj->hasSingletonType() && !obj->type()->maybeGetProperty(id, cx->asJSContext()))
return false;
return true;
@ -587,21 +587,23 @@ EnsureTrackPropertyTypes(JSContext *cx, JSObject *obj, jsid id)
/* Add a possible type for a property of obj. */
inline void
AddTypePropertyId(JSContext *cx, JSObject *obj, jsid id, Type type)
AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, Type type)
{
if (cx->typeInferenceEnabled())
if (cx->typeInferenceEnabled()) {
id = IdToTypeId(id);
if (TrackPropertyTypes(cx, obj, id))
obj->type()->addPropertyType(cx, id, type);
if (TrackPropertyTypes(cx, obj, id))
obj->type()->addPropertyType(cx->asJSContext(), id, type);
}
}
inline void
AddTypePropertyId(JSContext *cx, JSObject *obj, jsid id, const Value &value)
AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, const Value &value)
{
if (cx->typeInferenceEnabled())
if (cx->typeInferenceEnabled()) {
id = IdToTypeId(id);
if (TrackPropertyTypes(cx, obj, id))
obj->type()->addPropertyType(cx, id, value);
if (TrackPropertyTypes(cx, obj, id))
obj->type()->addPropertyType(cx->asJSContext(), id, value);
}
}
inline void
@ -620,10 +622,10 @@ AddTypeProperty(JSContext *cx, TypeObject *obj, const char *name, const Value &v
/* Set one or more dynamic flags on a type object. */
inline void
MarkTypeObjectFlags(JSContext *cx, JSObject *obj, TypeObjectFlags flags)
MarkTypeObjectFlags(ExclusiveContext *cx, JSObject *obj, TypeObjectFlags flags)
{
if (cx->typeInferenceEnabled() && !obj->hasLazyType() && !obj->type()->hasAllFlags(flags))
obj->type()->setFlags(cx, flags);
obj->type()->setFlags(cx->asJSContext(), flags);
}
/*
@ -649,20 +651,21 @@ MarkTypeObjectUnknownProperties(JSContext *cx, TypeObject *obj,
* have a getter/setter.
*/
inline void
MarkTypePropertyConfigured(JSContext *cx, HandleObject obj, jsid id)
MarkTypePropertyConfigured(ExclusiveContext *cx, HandleObject obj, jsid id)
{
if (cx->typeInferenceEnabled())
if (cx->typeInferenceEnabled()) {
id = IdToTypeId(id);
if (TrackPropertyTypes(cx, obj, id))
obj->type()->markPropertyConfigured(cx, id);
if (TrackPropertyTypes(cx, obj, id))
obj->type()->markPropertyConfigured(cx->asJSContext(), id);
}
}
/* Mark a state change on a particular object. */
inline void
MarkObjectStateChange(JSContext *cx, JSObject *obj)
MarkObjectStateChange(ExclusiveContext *cx, JSObject *obj)
{
if (cx->typeInferenceEnabled() && !obj->hasLazyType() && !obj->type()->unknownProperties())
obj->type()->markStateChange(cx);
obj->type()->markStateChange(cx->asJSContext());
}
/*
@ -671,17 +674,23 @@ MarkObjectStateChange(JSContext *cx, JSObject *obj)
*/
inline void
FixArrayType(JSContext *cx, HandleObject obj)
FixArrayType(ExclusiveContext *cxArg, HandleObject obj)
{
if (cx->typeInferenceEnabled())
cx->compartment()->types.fixArrayType(cx, obj);
if (cxArg->isJSContext()) {
JSContext *cx = cxArg->asJSContext();
if (cx->typeInferenceEnabled())
cx->compartment()->types.fixArrayType(cx, obj);
}
}
inline void
FixObjectType(JSContext *cx, HandleObject obj)
FixObjectType(ExclusiveContext *cxArg, HandleObject obj)
{
if (cx->typeInferenceEnabled())
cx->compartment()->types.fixObjectType(cx, obj);
if (cxArg->isJSContext()) {
JSContext *cx = cxArg->asJSContext();
if (cx->typeInferenceEnabled())
cx->compartment()->types.fixObjectType(cx, obj);
}
}
/* Interface helpers for JSScript*. */
@ -785,7 +794,7 @@ TypeScript::StandardType(JSContext *cx, JSProtoKey key)
RootedObject proto(cx);
if (!js_GetClassPrototype(cx, key, &proto, NULL))
return NULL;
return proto->getNewType(cx, GetClassForProtoKey(key));
return cx->getNewType(GetClassForProtoKey(key), proto.get());
}
struct AllocationSiteKey {

View File

@ -342,7 +342,7 @@ GetCustomIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandle
* trace, so the object we are iterating over is on top of the stack (-1).
*/
JSAutoByteString bytes;
if (!js_AtomToPrintableString(cx, name, &bytes))
if (!AtomToPrintableString(cx, name, &bytes))
return false;
RootedValue val(cx, ObjectValue(*obj));
js_ReportValueError2(cx, JSMSG_BAD_TRAP_RETURN_VALUE,
@ -375,7 +375,7 @@ static inline PropertyIteratorObject *
NewPropertyIteratorObject(JSContext *cx, unsigned flags)
{
if (flags & JSITER_ENUMERATE) {
RootedTypeObject type(cx, cx->compartment()->getNewType(cx, &PropertyIteratorObject::class_, NULL));
RootedTypeObject type(cx, cx->getNewType(&PropertyIteratorObject::class_, NULL));
if (!type)
return NULL;

View File

@ -53,7 +53,8 @@ using mozilla::RangedPtr;
* js_strtod_harder to get the correct answer.
*/
static bool
ComputeAccurateDecimalInteger(JSContext *cx, const jschar *start, const jschar *end, double *dp)
ComputeAccurateDecimalInteger(ExclusiveContext *cx,
const jschar *start, const jschar *end, double *dp)
{
size_t length = end - start;
char *cstr = cx->pod_malloc<char>(length + 1);
@ -69,9 +70,9 @@ ComputeAccurateDecimalInteger(JSContext *cx, const jschar *start, const jschar *
char *estr;
int err = 0;
*dp = js_strtod_harder(cx->mainThread().dtoaState, cstr, &estr, &err);
*dp = js_strtod_harder(cx->dtoaState(), cstr, &estr, &err);
if (err == JS_DTOA_ENOMEM) {
JS_ReportOutOfMemory(cx);
js_ReportOutOfMemory(cx);
js_free(cstr);
return false;
}
@ -186,7 +187,7 @@ js::ParseDecimalNumber(const JS::TwoByteChars chars)
}
bool
js::GetPrefixInteger(JSContext *cx, const jschar *start, const jschar *end, int base,
js::GetPrefixInteger(ExclusiveContext *cx, const jschar *start, const jschar *end, int base,
const jschar **endp, double *dp)
{
JS_ASSERT(start <= end);
@ -510,26 +511,24 @@ ToCStringBuf::~ToCStringBuf()
template <AllowGC allowGC>
JSFlatString *
js::Int32ToString(ThreadSafeContext *tcx, int32_t si)
js::Int32ToString(ThreadSafeContext *cx, int32_t si)
{
uint32_t ui;
if (si >= 0) {
if (StaticStrings::hasInt(si))
return tcx->staticStrings().getInt(si);
return cx->staticStrings().getInt(si);
ui = si;
} else {
ui = uint32_t(-si);
JS_ASSERT_IF(si == INT32_MIN, ui == uint32_t(INT32_MAX) + 1);
}
JSCompartment *c = NULL;
if (tcx->isJSContext()) {
c = tcx->asJSContext()->compartment();
if (JSFlatString *str = c->dtoaCache.lookup(10, si))
if (cx->isExclusiveContext()) {
if (JSFlatString *str = cx->asExclusiveContext()->dtoaCache().lookup(10, si))
return str;
}
JSShortString *str = js_NewGCShortString<allowGC>(tcx);
JSShortString *str = js_NewGCShortString<allowGC>(cx);
if (!str)
return NULL;
@ -544,12 +543,8 @@ js::Int32ToString(ThreadSafeContext *tcx, int32_t si)
jschar *dst = str->init(end - start);
PodCopy(dst, start.get(), end - start + 1);
/*
* Only attempt to cache the result if we have a JSContext, as it is
* racy.
*/
if (c)
c->dtoaCache.cache(10, si, str);
if (cx->isExclusiveContext())
cx->asExclusiveContext()->dtoaCache().cache(10, si, str);
return str;
}
@ -1194,7 +1189,7 @@ js_InitNumberClass(JSContext *cx, HandleObject obj)
}
static char *
FracNumberToCString(ThreadSafeContext *tcx, ToCStringBuf *cbuf, double d, int base = 10)
FracNumberToCString(ThreadSafeContext *cx, ToCStringBuf *cbuf, double d, int base = 10)
{
#ifdef DEBUG
{
@ -1218,7 +1213,7 @@ FracNumberToCString(ThreadSafeContext *tcx, ToCStringBuf *cbuf, double d, int ba
converter.ToShortest(d, &builder);
numStr = builder.Finalize();
} else {
numStr = cbuf->dbuf = js_dtobasestr(tcx->perThreadData->dtoaState, base, d);
numStr = cbuf->dbuf = js_dtobasestr(cx->dtoaState(), base, d);
}
return numStr;
}
@ -1234,7 +1229,7 @@ js::NumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base/* = 10
template <AllowGC allowGC>
static JSString * JS_FASTCALL
js_NumberToStringWithBase(ThreadSafeContext *tcx, double d, int base)
js_NumberToStringWithBase(ThreadSafeContext *cx, double d, int base)
{
ToCStringBuf cbuf;
char *numStr;
@ -1247,38 +1242,34 @@ js_NumberToStringWithBase(ThreadSafeContext *tcx, double d, int base)
if (base < 2 || base > 36)
return NULL;
JSCompartment *c = NULL;
JSContext *cx = NULL;
if (tcx->isJSContext()) {
cx = tcx->asJSContext();
c = cx->compartment();
}
int32_t i;
if (mozilla::DoubleIsInt32(d, &i)) {
if (base == 10 && StaticStrings::hasInt(i))
return tcx->staticStrings().getInt(i);
return cx->staticStrings().getInt(i);
if (unsigned(i) < unsigned(base)) {
if (i < 10)
return tcx->staticStrings().getInt(i);
return cx->staticStrings().getInt(i);
jschar c = 'a' + i - 10;
JS_ASSERT(StaticStrings::hasUnit(c));
return tcx->staticStrings().getUnit(c);
return cx->staticStrings().getUnit(c);
}
if (JSFlatString *str = c ? c->dtoaCache.lookup(base, d) : NULL)
return str;
if (cx->isExclusiveContext()) {
if (JSFlatString *str = cx->asExclusiveContext()->dtoaCache().lookup(base, d))
return str;
}
numStr = IntToCString(&cbuf, i, base);
JS_ASSERT(!cbuf.dbuf && numStr >= cbuf.sbuf && numStr < cbuf.sbuf + cbuf.sbufSize);
} else {
if (JSFlatString *str = c ? c->dtoaCache.lookup(base, d) : NULL)
return str;
if (cx->isExclusiveContext()) {
if (JSFlatString *str = cx->asExclusiveContext()->dtoaCache().lookup(base, d))
return str;
}
numStr = FracNumberToCString(tcx, &cbuf, d, base);
numStr = FracNumberToCString(cx, &cbuf, d, base);
if (!numStr) {
if (cx)
JS_ReportOutOfMemory(cx);
js_ReportOutOfMemory(cx);
return NULL;
}
JS_ASSERT_IF(base == 10,
@ -1287,29 +1278,26 @@ js_NumberToStringWithBase(ThreadSafeContext *tcx, double d, int base)
cbuf.dbuf && cbuf.dbuf == numStr);
}
JSFlatString *s = js_NewStringCopyZ<allowGC>(tcx, numStr);
JSFlatString *s = js_NewStringCopyZ<allowGC>(cx, numStr);
if (cx->isExclusiveContext())
cx->asExclusiveContext()->dtoaCache().cache(base, d, s);
/*
* We will only cache dtoa results if we have a JSContext, as it is
* racy.
*/
if (c)
c->dtoaCache.cache(base, d, s);
return s;
}
template <AllowGC allowGC>
JSString *
js_NumberToString(ThreadSafeContext *tcx, double d)
js_NumberToString(ThreadSafeContext *cx, double d)
{
return js_NumberToStringWithBase<allowGC>(tcx, d, 10);
return js_NumberToStringWithBase<allowGC>(cx, d, 10);
}
template JSString *
js_NumberToString<CanGC>(ThreadSafeContext *tcx, double d);
js_NumberToString<CanGC>(ThreadSafeContext *cx, double d);
template JSString *
js_NumberToString<NoGC>(ThreadSafeContext *tcx, double d);
js_NumberToString<NoGC>(ThreadSafeContext *cx, double d);
JSFlatString *
js::NumberToString(JSContext *cx, double d)
@ -1372,7 +1360,7 @@ js::NumberValueToStringBuffer(JSContext *cx, const Value &v, StringBuffer &sb)
}
bool
js::StringToNumber(JSContext *cx, JSString *str, double *result)
js::StringToNumber(ExclusiveContext *cx, JSString *str, double *result)
{
size_t length = str->length();
const jschar *chars = str->getChars(NULL);
@ -1436,8 +1424,9 @@ js::StringToNumber(JSContext *cx, JSString *str, double *result)
#if defined(_MSC_VER)
# pragma optimize("g", off)
#endif
JS_PUBLIC_API(bool)
js::ToNumberSlow(JSContext *cx, Value v, double *out)
bool
js::ToNumberSlow(ExclusiveContext *cx, Value v, double *out)
{
#ifdef DEBUG
/*
@ -1485,7 +1474,7 @@ js::ToNumberSlow(JSContext *cx, Value v, double *out)
JS_ASSERT(v.isObject());
RootedValue v2(cx, v);
if (!ToPrimitive(cx, JSTYPE_NUMBER, &v2))
if (!ToPrimitive(cx->asJSContext(), JSTYPE_NUMBER, &v2))
return false;
v = v2;
if (v.isObject())
@ -1495,6 +1484,13 @@ js::ToNumberSlow(JSContext *cx, Value v, double *out)
*out = js_NaN;
return true;
}
JS_PUBLIC_API(bool)
js::ToNumberSlow(JSContext *cx, Value v, double *out)
{
return ToNumberSlow(static_cast<ExclusiveContext *>(cx), v, out);
}
#if defined(_MSC_VER)
# pragma optimize("", on)
#endif
@ -1601,7 +1597,7 @@ js::ToUint16Slow(JSContext *cx, const Value &v, uint16_t *out)
}
JSBool
js_strtod(JSContext *cx, const jschar *s, const jschar *send,
js_strtod(ExclusiveContext *cx, const jschar *s, const jschar *send,
const jschar **ep, double *dp)
{
size_t i;
@ -1637,7 +1633,7 @@ js_strtod(JSContext *cx, const jschar *s, const jschar *send,
estr = istr + 8;
} else {
int err;
d = js_strtod_harder(cx->mainThread().dtoaState, cstr, &estr, &err);
d = js_strtod_harder(cx->dtoaState(), cstr, &estr, &err);
if (d == HUGE_VAL)
d = js_PositiveInfinity;
else if (d == -HUGE_VAL)

View File

@ -55,7 +55,7 @@ namespace js {
template <AllowGC allowGC>
extern JSFlatString *
Int32ToString(ThreadSafeContext *tcx, int32_t i);
Int32ToString(ThreadSafeContext *cx, int32_t i);
/*
* Convert an integer or double (contained in the given value) to a string and
@ -128,11 +128,11 @@ ParseDecimalNumber(const JS::TwoByteChars chars);
* *dp == 0 and *endp == start upon return.
*/
extern bool
GetPrefixInteger(JSContext *cx, const jschar *start, const jschar *end, int base,
GetPrefixInteger(ExclusiveContext *cx, const jschar *start, const jschar *end, int base,
const jschar **endp, double *dp);
extern bool
StringToNumber(JSContext *cx, JSString *str, double *result);
StringToNumber(ExclusiveContext *cx, JSString *str, double *result);
/* ES5 9.3 ToNumber, overwriting *vp with the appropriate number value. */
JS_ALWAYS_INLINE bool
@ -169,7 +169,7 @@ num_parseInt(JSContext *cx, unsigned argc, Value *vp);
* Return false if out of memory.
*/
extern JSBool
js_strtod(JSContext *cx, const jschar *s, const jschar *send,
js_strtod(js::ExclusiveContext *cx, const jschar *s, const jschar *send,
const jschar **ep, double *dp);
extern JSBool
@ -263,6 +263,21 @@ SafeMul(int32_t one, int32_t two, int32_t *res)
return ores == (int64_t)*res;
}
extern bool
ToNumberSlow(ExclusiveContext *cx, Value v, double *dp);
// Variant of ToNumber which takes an ExclusiveContext instead of a JSContext.
// ToNumber is part of the API and can't use ExclusiveContext directly.
JS_ALWAYS_INLINE bool
ToNumber(ExclusiveContext *cx, const Value &v, double *out)
{
if (v.isNumber()) {
*out = v.toNumber();
return true;
}
return ToNumberSlow(cx, v, out);
}
} /* namespace js */
#endif /* jsnum_h */

View File

@ -1291,13 +1291,13 @@ NewObjectGCKind(js::Class *clasp)
}
static inline JSObject *
NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *parent,
NewObject(ExclusiveContext *cx, Class *clasp, types::TypeObject *type_, JSObject *parent,
gc::AllocKind kind, NewObjectKind newKind)
{
JS_ASSERT(clasp != &ArrayObject::class_);
JS_ASSERT_IF(clasp == &JSFunction::class_,
kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
JS_ASSERT_IF(parent, &parent->global() == cx->compartment()->maybeGlobal());
JS_ASSERT_IF(parent, &parent->global() == cx->global());
RootedTypeObject type(cx, type_);
@ -1327,7 +1327,7 @@ NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *paren
* slices, and it will prevent any future incremental GCs.
*/
if (clasp->trace && !(clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS))
cx->runtime()->gcIncrementalEnabled = false;
cx->asJSContext()->runtime()->gcIncrementalEnabled = false;
Probes::createObject(cx, obj);
return obj;
@ -1343,33 +1343,34 @@ NewObjectCache::fillProto(EntryIndex entry, Class *clasp, js::TaggedProto proto,
}
JSObject *
js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp,
js::NewObjectWithGivenProto(ExclusiveContext *cxArg, js::Class *clasp,
js::TaggedProto proto_, JSObject *parent_,
gc::AllocKind allocKind, NewObjectKind newKind)
{
Rooted<TaggedProto> proto(cx, proto_);
RootedObject parent(cx, parent_);
Rooted<TaggedProto> proto(cxArg, proto_);
RootedObject parent(cxArg, parent_);
if (CanBeFinalizedInBackground(allocKind, clasp))
allocKind = GetBackgroundAllocKind(allocKind);
NewObjectCache &cache = cx->runtime()->newObjectCache;
NewObjectCache::EntryIndex entry = -1;
if (proto.isObject() &&
newKind == GenericObject &&
!cx->compartment()->objectMetadataCallback &&
(!parent || parent == proto.toObject()->getParent()) &&
!proto.toObject()->is<GlobalObject>())
{
if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
if (obj)
return obj;
if (JSContext *cx = cxArg->maybeJSContext()) {
NewObjectCache &cache = cx->runtime()->newObjectCache;
if (proto.isObject() &&
newKind == GenericObject &&
!cx->compartment()->objectMetadataCallback &&
(!parent || parent == proto.toObject()->getParent()) &&
!proto.toObject()->is<GlobalObject>())
{
if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
if (obj)
return obj;
}
}
}
types::TypeObject *type = cx->compartment()->getNewType(cx, clasp, proto, NULL);
types::TypeObject *type = cxArg->getNewType(clasp, proto, NULL);
if (!type)
return NULL;
@ -1380,28 +1381,31 @@ js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp,
if (!parent && proto.isObject())
parent = proto.toObject()->getParent();
RootedObject obj(cx, NewObject(cx, clasp, type, parent, allocKind, newKind));
RootedObject obj(cxArg, NewObject(cxArg, clasp, type, parent, allocKind, newKind));
if (!obj)
return NULL;
if (entry != -1 && !obj->hasDynamicSlots())
cache.fillProto(entry, clasp, proto, allocKind, obj);
if (entry != -1 && !obj->hasDynamicSlots()) {
cxArg->asJSContext()->runtime()->newObjectCache.fillProto(entry, clasp,
proto, allocKind, obj);
}
return obj;
}
JSObject *
js::NewObjectWithClassProtoCommon(JSContext *cx, js::Class *clasp, JSObject *protoArg, JSObject *parentArg,
js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg,
js::Class *clasp, JSObject *protoArg, JSObject *parentArg,
gc::AllocKind allocKind, NewObjectKind newKind)
{
if (protoArg)
return NewObjectWithGivenProto(cx, clasp, protoArg, parentArg, allocKind, newKind);
return NewObjectWithGivenProto(cxArg, clasp, protoArg, parentArg, allocKind, newKind);
if (CanBeFinalizedInBackground(allocKind, clasp))
allocKind = GetBackgroundAllocKind(allocKind);
if (!parentArg)
parentArg = cx->global();
parentArg = cxArg->global();
/*
* Use the object cache, except for classes without a cached proto key.
@ -1414,37 +1418,41 @@ js::NewObjectWithClassProtoCommon(JSContext *cx, js::Class *clasp, JSObject *pro
*/
JSProtoKey protoKey = GetClassProtoKey(clasp);
NewObjectCache &cache = cx->runtime()->newObjectCache;
NewObjectCache::EntryIndex entry = -1;
if (parentArg->is<GlobalObject>() &&
protoKey != JSProto_Null &&
newKind == GenericObject &&
!cx->compartment()->objectMetadataCallback)
{
if (cache.lookupGlobal(clasp, &parentArg->as<GlobalObject>(), allocKind, &entry)) {
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
if (obj)
return obj;
if (JSContext *cx = cxArg->maybeJSContext()) {
NewObjectCache &cache = cx->runtime()->newObjectCache;
if (parentArg->is<GlobalObject>() &&
protoKey != JSProto_Null &&
newKind == GenericObject &&
!cx->compartment()->objectMetadataCallback)
{
if (cache.lookupGlobal(clasp, &parentArg->as<GlobalObject>(), allocKind, &entry)) {
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
if (obj)
return obj;
}
}
}
RootedObject parent(cx, parentArg);
RootedObject proto(cx, protoArg);
RootedObject parent(cxArg, parentArg);
RootedObject proto(cxArg, protoArg);
if (!FindProto(cx, clasp, &proto))
if (!FindProto(cxArg, clasp, &proto))
return NULL;
types::TypeObject *type = proto->getNewType(cx, clasp);
types::TypeObject *type = cxArg->getNewType(clasp, proto.get());
if (!type)
return NULL;
JSObject *obj = NewObject(cx, clasp, type, parent, allocKind, newKind);
JSObject *obj = NewObject(cxArg, clasp, type, parent, allocKind, newKind);
if (!obj)
return NULL;
if (entry != -1 && !obj->hasDynamicSlots())
cache.fillGlobal(entry, clasp, &parent->as<GlobalObject>(), allocKind, obj);
if (entry != -1 && !obj->hasDynamicSlots()) {
cxArg->asJSContext()->runtime()->newObjectCache.fillGlobal(entry, clasp,
&parent->as<GlobalObject>(),
allocKind, obj);
}
return obj;
}
@ -1597,7 +1605,7 @@ js::CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject
RootedObject res(cx);
if (proto) {
RootedTypeObject type(cx, proto->getNewType(cx, &ObjectClass, &callee->as<JSFunction>()));
RootedTypeObject type(cx, cx->getNewType(&ObjectClass, proto, &callee->as<JSFunction>()));
if (!type)
return NULL;
res = CreateThisForFunctionWithType(cx, type, callee->getParent(), newKind);
@ -1864,7 +1872,7 @@ JSObject *
js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
{
Rooted<TypeObject*> typeObj(cx);
typeObj = cx->global()->getOrCreateObjectPrototype(cx)->getNewType(cx, &ObjectClass);
typeObj = cx->getNewType(&ObjectClass, cx->global()->getOrCreateObjectPrototype(cx));
JS_ASSERT(srcObj->getClass() == &ObjectClass);
AllocKind kind = GetBackgroundAllocKind(GuessObjectGCKind(srcObj->numFixedSlots()));
@ -2452,7 +2460,8 @@ js_InitClass(JSContext *cx, HandleObject obj, JSObject *protoProto_,
}
/* static */ inline bool
JSObject::updateSlotsForSpan(JSContext *cx, HandleObject obj, size_t oldSpan, size_t newSpan)
JSObject::updateSlotsForSpan(ExclusiveContext *cx,
HandleObject obj, size_t oldSpan, size_t newSpan)
{
JS_ASSERT(oldSpan != newSpan);
@ -2480,7 +2489,7 @@ JSObject::updateSlotsForSpan(JSContext *cx, HandleObject obj, size_t oldSpan, si
}
/* static */ bool
JSObject::setLastProperty(JSContext *cx, HandleObject obj, HandleShape shape)
JSObject::setLastProperty(ExclusiveContext *cx, HandleObject obj, HandleShape shape)
{
JS_ASSERT(!obj->inDictionaryMode());
JS_ASSERT(!shape->inDictionary());
@ -2503,7 +2512,7 @@ JSObject::setLastProperty(JSContext *cx, HandleObject obj, HandleShape shape)
}
/* static */ bool
JSObject::setSlotSpan(JSContext *cx, HandleObject obj, uint32_t span)
JSObject::setSlotSpan(ExclusiveContext *cx, HandleObject obj, uint32_t span)
{
JS_ASSERT(obj->inDictionaryMode());
@ -2519,29 +2528,32 @@ JSObject::setSlotSpan(JSContext *cx, HandleObject obj, uint32_t span)
}
static HeapSlot *
AllocateSlots(JSContext *cx, JSObject *obj, uint32_t nslots)
AllocateSlots(ExclusiveContext *cx, JSObject *obj, uint32_t nslots)
{
#ifdef JSGC_GENERATIONAL
return cx->runtime()->gcNursery.allocateSlots(cx, obj, nslots);
#else
return cx->pod_malloc<HeapSlot>(nslots);
if (cx->isJSContext())
return cx->asJSContext()->runtime()->gcNursery.allocateSlots(cx->asJSContext(), obj, nslots);
#endif
return cx->pod_malloc<HeapSlot>(nslots);
}
static HeapSlot *
ReallocateSlots(JSContext *cx, JSObject *obj, HeapSlot *oldSlots,
ReallocateSlots(ExclusiveContext *cx, JSObject *obj, HeapSlot *oldSlots,
uint32_t oldCount, uint32_t newCount)
{
#ifdef JSGC_GENERATIONAL
return cx->runtime()->gcNursery.reallocateSlots(cx, obj, oldSlots, oldCount, newCount);
#else
if (cx->isJSContext()) {
return cx->asJSContext()->runtime()->gcNursery.reallocateSlots(cx->asJSContext(),
obj, oldSlots,
oldCount, newCount);
}
#endif
return (HeapSlot *)cx->realloc_(oldSlots, oldCount * sizeof(HeapSlot),
newCount * sizeof(HeapSlot));
#endif
}
/* static */ bool
JSObject::growSlots(JSContext *cx, HandleObject obj, uint32_t oldCount, uint32_t newCount)
JSObject::growSlots(ExclusiveContext *cx, HandleObject obj, uint32_t oldCount, uint32_t newCount)
{
JS_ASSERT(newCount > oldCount);
JS_ASSERT(newCount >= SLOT_CAPACITY_MIN);
@ -2562,18 +2574,22 @@ JSObject::growSlots(JSContext *cx, HandleObject obj, uint32_t oldCount, uint32_t
if (!obj->hasLazyType() && !oldCount && obj->type()->newScript) {
gc::AllocKind kind = obj->type()->newScript->allocKind;
uint32_t newScriptSlots = gc::GetGCKindSlots(kind);
if (newScriptSlots == obj->numFixedSlots() && gc::TryIncrementAllocKind(&kind)) {
AutoEnterAnalysis enter(cx);
if (newScriptSlots == obj->numFixedSlots() &&
gc::TryIncrementAllocKind(&kind) &&
cx->isJSContext())
{
JSContext *ncx = cx->asJSContext();
AutoEnterAnalysis enter(ncx);
Rooted<TypeObject*> typeObj(cx, obj->type());
RootedShape shape(cx, typeObj->newScript->shape);
JSObject *reshapedObj = NewReshapedObject(cx, typeObj, obj->getParent(), kind, shape);
JSObject *reshapedObj = NewReshapedObject(ncx, typeObj, obj->getParent(), kind, shape);
if (!reshapedObj)
return false;
typeObj->newScript->allocKind = kind;
typeObj->newScript->shape = reshapedObj->lastProperty();
typeObj->markStateChange(cx);
typeObj->markStateChange(ncx);
}
}
@ -2602,16 +2618,16 @@ JSObject::growSlots(JSContext *cx, HandleObject obj, uint32_t oldCount, uint32_t
}
static void
FreeSlots(JSContext *cx, HeapSlot *slots)
FreeSlots(ExclusiveContext *cx, HeapSlot *slots)
{
#ifdef JSGC_GENERATIONAL
if (!cx->runtime()->gcNursery.isInside(slots))
if (!cx->isJSContext() || !cx->asJSContext()->runtime()->gcNursery.isInside(slots))
#endif
js_free(slots);
}
/* static */ void
JSObject::shrinkSlots(JSContext *cx, HandleObject obj, uint32_t oldCount, uint32_t newCount)
JSObject::shrinkSlots(ExclusiveContext *cx, HandleObject obj, uint32_t oldCount, uint32_t newCount)
{
JS_ASSERT(newCount < oldCount);
@ -2636,7 +2652,7 @@ JSObject::shrinkSlots(JSContext *cx, HandleObject obj, uint32_t oldCount, uint32
}
/* static */ bool
JSObject::sparsifyDenseElement(JSContext *cx, HandleObject obj, uint32_t index)
JSObject::sparsifyDenseElement(ExclusiveContext *cx, HandleObject obj, uint32_t index)
{
RootedValue value(cx, obj->getDenseElement(index));
JS_ASSERT(!value.isMagic(JS_ELEMENTS_HOLE));
@ -2656,7 +2672,7 @@ JSObject::sparsifyDenseElement(JSContext *cx, HandleObject obj, uint32_t index)
}
/* static */ bool
JSObject::sparsifyDenseElements(JSContext *cx, HandleObject obj)
JSObject::sparsifyDenseElements(js::ExclusiveContext *cx, HandleObject obj)
{
uint32_t initialized = obj->getDenseInitializedLength();
@ -2715,7 +2731,7 @@ JSObject::willBeSparseElements(uint32_t requiredCapacity, uint32_t newElementsHi
}
/* static */ JSObject::EnsureDenseResult
JSObject::maybeDensifySparseElements(JSContext *cx, HandleObject obj)
JSObject::maybeDensifySparseElements(js::ExclusiveContext *cx, HandleObject obj)
{
/*
* Wait until after the object goes into dictionary mode, which must happen
@ -2921,7 +2937,7 @@ JSObject::growElements(ThreadSafeContext *tcx, uint32_t newcap)
}
void
JSObject::shrinkElements(JSContext *cx, uint32_t newcap)
JSObject::shrinkElements(ThreadSafeContext *cx, uint32_t newcap)
{
uint32_t oldcap = getDenseCapacity();
JS_ASSERT(newcap <= oldcap);
@ -3031,7 +3047,7 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj,
return false;
}
TypeObject *type = cx->compartment()->getNewType(cx, clasp, proto);
TypeObject *type = cx->getNewType(clasp, proto);
if (!type)
return false;
@ -3051,9 +3067,9 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj,
}
bool
js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, MutableHandleObject objp)
js_GetClassObject(ExclusiveContext *cxArg, JSObject *obj, JSProtoKey key, MutableHandleObject objp)
{
RootedObject global(cx, &obj->global());
RootedObject global(cxArg, &obj->global());
if (!global->is<GlobalObject>()) {
objp.set(NULL);
return true;
@ -3065,6 +3081,9 @@ js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, MutableHandleObj
return true;
}
// Classes can only be initialized on the main thread.
JSContext *cx = cxArg->asJSContext();
RootedId name(cx, NameToId(ClassName(key, cx)));
AutoResolving resolving(cx, global, name);
if (resolving.alreadyStarted()) {
@ -3110,7 +3129,7 @@ js_IdentifyClassPrototype(JSObject *obj)
}
bool
js_FindClassObject(JSContext *cx, JSProtoKey protoKey, MutableHandleValue vp, Class *clasp)
js_FindClassObject(ExclusiveContext *cx, JSProtoKey protoKey, MutableHandleValue vp, Class *clasp)
{
RootedId id(cx);
@ -3149,7 +3168,7 @@ js_FindClassObject(JSContext *cx, JSProtoKey protoKey, MutableHandleValue vp, Cl
}
/* static */ bool
JSObject::allocSlot(JSContext *cx, HandleObject obj, uint32_t *slotp)
JSObject::allocSlot(ExclusiveContext *cx, HandleObject obj, uint32_t *slotp)
{
uint32_t slot = obj->slotSpan();
JS_ASSERT(slot >= JSSLOT_FREE(obj->getClass()));
@ -3216,7 +3235,7 @@ JSObject::freeSlot(uint32_t slot)
}
static bool
PurgeProtoChain(JSContext *cx, JSObject *objArg, HandleId id)
PurgeProtoChain(ExclusiveContext *cx, JSObject *objArg, HandleId id)
{
/* Root locally so we can re-assign. */
RootedObject obj(cx, objArg);
@ -3242,7 +3261,7 @@ PurgeProtoChain(JSContext *cx, JSObject *objArg, HandleId id)
}
static bool
PurgeScopeChainHelper(JSContext *cx, HandleObject objArg, HandleId id)
PurgeScopeChainHelper(ExclusiveContext *cx, HandleObject objArg, HandleId id)
{
/* Re-root locally so we can re-assign. */
RootedObject obj(cx, objArg);
@ -3279,14 +3298,13 @@ PurgeScopeChainHelper(JSContext *cx, HandleObject objArg, HandleId id)
* (i.e., obj has ever been on a prototype or parent chain).
*/
static inline bool
PurgeScopeChain(JSContext *cx, JS::HandleObject obj, JS::HandleId id)
PurgeScopeChain(ExclusiveContext *cx, JS::HandleObject obj, JS::HandleId id)
{
if (obj->isDelegate())
return PurgeScopeChainHelper(cx, obj, id);
return true;
}
Shape *
js_AddNativeProperty(JSContext *cx, HandleObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter, uint32_t slot,
@ -3312,14 +3330,44 @@ js_AddNativeProperty(JSContext *cx, HandleObject obj, HandleId id,
}
JSBool
baseops::DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
baseops::DefineGeneric(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
}
/* static */ JSBool
JSObject::defineGeneric(ExclusiveContext *cx, HandleObject obj,
HandleId id, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
js::DefineGenericOp op = obj->getOps()->defineGeneric;
if (op)
return op(cx->asJSContext(), obj, id, value, getter, setter, attrs);
return baseops::DefineGeneric(cx, obj, id, value, getter, setter, attrs);
}
/* static */ JSBool
JSObject::defineProperty(ExclusiveContext *cx, HandleObject obj,
PropertyName *name, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
RootedId id(cx, NameToId(name));
return defineGeneric(cx, obj, id, value, getter, setter, attrs);
}
/* static */ JSBool
JSObject::defineSpecial(ExclusiveContext *cx, HandleObject obj,
SpecialId sid, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
RootedId id(cx, SPECIALID_TO_JSID(sid));
return defineGeneric(cx, obj, id, value, getter, setter, attrs);
}
JSBool
baseops::DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
baseops::DefineElement(ExclusiveContext *cx, HandleObject obj, uint32_t index, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
Rooted<jsid> id(cx);
@ -3336,6 +3384,36 @@ baseops::DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleVa
return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
}
/* static */ JSBool
JSObject::defineElement(ExclusiveContext *cx, HandleObject obj,
uint32_t index, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
js::DefineElementOp op = obj->getOps()->defineElement;
if (op)
return op(cx->asJSContext(), obj, index, value, getter, setter, attrs);
return baseops::DefineElement(cx, obj, index, value, getter, setter, attrs);
}
Shape *
JSObject::addDataProperty(ExclusiveContext *cx, jsid idArg, uint32_t slot, unsigned attrs)
{
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
RootedObject self(cx, this);
RootedId id(cx, idArg);
return addProperty(cx, self, id, NULL, NULL, slot, attrs, 0, 0);
}
Shape *
JSObject::addDataProperty(ExclusiveContext *cx, HandlePropertyName name,
uint32_t slot, unsigned attrs)
{
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
RootedObject self(cx, this);
RootedId id(cx, NameToId(name));
return addProperty(cx, self, id, NULL, NULL, slot, attrs, 0, 0);
}
/*
* Backward compatibility requires allowing addProperty hooks to mutate the
* nominal initial value of a slotful property, while GC safety wants that
@ -3343,7 +3421,7 @@ baseops::DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleVa
* both while saving cycles for classes that stub their addProperty hook.
*/
static inline bool
CallAddPropertyHook(JSContext *cx, Class *clasp, HandleObject obj, HandleShape shape,
CallAddPropertyHook(ExclusiveContext *cx, Class *clasp, HandleObject obj, HandleShape shape,
HandleValue nominal)
{
if (clasp->addProperty != JS_PropertyStub) {
@ -3351,7 +3429,7 @@ CallAddPropertyHook(JSContext *cx, Class *clasp, HandleObject obj, HandleShape s
RootedValue value(cx, nominal);
Rooted<jsid> id(cx, shape->propid());
if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value)) {
if (!CallJSPropertyOp(cx->asJSContext(), clasp->addProperty, obj, id, &value)) {
obj->removeProperty(cx, shape->propid());
return false;
}
@ -3364,7 +3442,7 @@ CallAddPropertyHook(JSContext *cx, Class *clasp, HandleObject obj, HandleShape s
}
static inline bool
CallAddPropertyHookDense(JSContext *cx, Class *clasp, HandleObject obj, uint32_t index,
CallAddPropertyHookDense(ExclusiveContext *cx, Class *clasp, HandleObject obj, uint32_t index,
HandleValue nominal)
{
/* Inline addProperty for array objects. */
@ -3372,7 +3450,7 @@ CallAddPropertyHookDense(JSContext *cx, Class *clasp, HandleObject obj, uint32_t
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
uint32_t length = arr->length();
if (index >= length)
ArrayObject::setLength(cx, arr, index + 1);
ArrayObject::setLength(cx->asJSContext(), arr, index + 1);
return true;
}
@ -3381,7 +3459,7 @@ CallAddPropertyHookDense(JSContext *cx, Class *clasp, HandleObject obj, uint32_t
RootedValue value(cx, nominal);
Rooted<jsid> id(cx, INT_TO_JSID(index));
if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value)) {
if (!CallJSPropertyOp(cx->asJSContext(), clasp->addProperty, obj, id, &value)) {
JSObject::setDenseElementHole(cx, obj, index);
return false;
}
@ -3392,7 +3470,7 @@ CallAddPropertyHookDense(JSContext *cx, Class *clasp, HandleObject obj, uint32_t
}
static inline bool
DefinePropertyOrElement(JSContext *cx, HandleObject obj, HandleId id,
DefinePropertyOrElement(ExclusiveContext *cx, HandleObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
unsigned attrs, unsigned flags, int shortid,
HandleValue value, bool callSetterAfterwards, bool setterIsStrict)
@ -3423,7 +3501,7 @@ DefinePropertyOrElement(JSContext *cx, HandleObject obj, HandleId id,
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (id == NameToId(cx->names().length))
return ArraySetLength(cx, arr, id, attrs, value, setterIsStrict);
return ArraySetLength(cx->asJSContext(), arr, id, attrs, value, setterIsStrict);
uint32_t index;
if (js_IdIsIndex(id, &index)) {
@ -3467,13 +3545,13 @@ DefinePropertyOrElement(JSContext *cx, HandleObject obj, HandleId id,
if (callSetterAfterwards && setter != JS_StrictPropertyStub) {
RootedValue nvalue(cx, value);
return js_NativeSet(cx, obj, obj, shape, setterIsStrict, &nvalue);
return js_NativeSet(cx->asJSContext(), obj, obj, shape, setterIsStrict, &nvalue);
}
return true;
}
bool
js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
js::DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow /* = 0 */)
{
@ -3657,7 +3735,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
template <AllowGC allowGC>
static JS_ALWAYS_INLINE bool
LookupPropertyWithFlagsInline(JSContext *cx,
LookupPropertyWithFlagsInline(ExclusiveContext *cx,
typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id,
unsigned flags,
@ -3694,7 +3772,7 @@ LookupPropertyWithFlagsInline(JSContext *cx,
if (!allowGC)
return false;
bool recursed;
if (!CallResolveOp(cx,
if (!CallResolveOp(cx->asJSContext(),
MaybeRooted<JSObject*, allowGC>::toHandle(current),
MaybeRooted<jsid, allowGC>::toHandle(id),
flags,
@ -3723,7 +3801,7 @@ LookupPropertyWithFlagsInline(JSContext *cx,
if (!proto->isNative()) {
if (!allowGC)
return false;
return JSObject::lookupGeneric(cx,
return JSObject::lookupGeneric(cx->asJSContext(),
MaybeRooted<JSObject*, allowGC>::toHandle(proto),
MaybeRooted<jsid, allowGC>::toHandle(id),
MaybeRooted<JSObject*, allowGC>::toMutableHandle(objp),
@ -3740,7 +3818,7 @@ LookupPropertyWithFlagsInline(JSContext *cx,
template <AllowGC allowGC>
JSBool
baseops::LookupProperty(JSContext *cx,
baseops::LookupProperty(ExclusiveContext *cx,
typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id,
typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
@ -3750,18 +3828,35 @@ baseops::LookupProperty(JSContext *cx,
* |CanEffectlesslyCallLookupGenericOnObject| logic.
* If this changes, please remember to update the logic there as well.
*/
return LookupPropertyWithFlagsInline<allowGC>(cx, obj, id, cx->resolveFlags, objp, propp);
uint32_t resolveFlags =
cx->isJSContext() ? cx->asJSContext()->resolveFlags : 0;
return LookupPropertyWithFlagsInline<allowGC>(cx, obj, id, resolveFlags, objp, propp);
}
template JSBool
baseops::LookupProperty<CanGC>(JSContext *cx, HandleObject obj, HandleId id,
baseops::LookupProperty<CanGC>(ExclusiveContext *cx, HandleObject obj, HandleId id,
MutableHandleObject objp, MutableHandleShape propp);
template JSBool
baseops::LookupProperty<NoGC>(JSContext *cx, JSObject *obj, jsid id,
baseops::LookupProperty<NoGC>(ExclusiveContext *cx, JSObject *obj, jsid id,
FakeMutableHandle<JSObject*> objp,
FakeMutableHandle<Shape*> propp);
/* static */ JSBool
JSObject::lookupGeneric(JSContext *cx, HandleObject obj, js::HandleId id,
MutableHandleObject objp, MutableHandleShape propp)
{
/*
* NB: The logic of lookupGeneric is implicitly reflected in IonBuilder.cpp's
* |CanEffectlesslyCallLookupGenericOnObject| logic.
* If this changes, please remember to update the logic there as well.
*/
LookupGenericOp op = obj->getOps()->lookupGeneric;
if (op)
return op(cx, obj, id, objp, propp);
return baseops::LookupProperty<js::CanGC>(cx, obj, id, objp, propp);
}
JSBool
baseops::LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp)
@ -3774,7 +3869,7 @@ baseops::LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
}
bool
js::LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
js::LookupPropertyWithFlags(ExclusiveContext *cx, HandleObject obj, HandleId id, unsigned flags,
MutableHandleObject objp, MutableHandleShape propp)
{
return LookupPropertyWithFlagsInline<CanGC>(cx, obj, id, flags, objp, propp);
@ -4985,7 +5080,8 @@ js::IsDelegate(JSContext *cx, HandleObject obj, const js::Value &v, bool *result
* NewBuiltinClassInstance in jsobjinlines.h.
*/
bool
js_GetClassPrototype(JSContext *cx, JSProtoKey protoKey, MutableHandleObject protop, Class *clasp)
js_GetClassPrototype(ExclusiveContext *cx, JSProtoKey protoKey,
MutableHandleObject protop, Class *clasp)
{
JS_ASSERT(JSProto_Null <= protoKey);
JS_ASSERT(protoKey < JSProto_LIMIT);
@ -5004,8 +5100,17 @@ js_GetClassPrototype(JSContext *cx, JSProtoKey protoKey, MutableHandleObject pro
if (IsFunctionObject(v)) {
RootedObject ctor(cx, &v.get().toObject());
if (!JSObject::getProperty(cx, ctor, ctor, cx->names().classPrototype, &v))
return false;
if (cx->isJSContext()) {
if (!JSObject::getProperty(cx->asJSContext(),
ctor, ctor, cx->names().classPrototype, &v))
{
return false;
}
} else {
Shape *shape = ctor->nativeLookup(cx, cx->names().classPrototype);
if (!shape || !NativeGetPureInline(ctor, shape, v.address()))
return false;
}
}
protop.set(v.get().isObject() ? &v.get().toObject() : NULL);

View File

@ -102,38 +102,22 @@ namespace baseops {
*/
template <AllowGC allowGC>
extern JSBool
LookupProperty(JSContext *cx,
LookupProperty(ExclusiveContext *cx,
typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id,
typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp);
inline bool
LookupProperty(JSContext *cx, HandleObject obj, PropertyName *name,
MutableHandleObject objp, MutableHandleShape propp)
{
Rooted<jsid> id(cx, NameToId(name));
return LookupProperty<CanGC>(cx, obj, id, objp, propp);
}
extern JSBool
LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp);
extern JSBool
DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
DefineGeneric(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
inline JSBool
DefineProperty(JSContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
Rooted<jsid> id(cx, NameToId(name));
return DefineGeneric(cx, obj, id, value, getter, setter, attrs);
}
extern JSBool
DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
DefineElement(ExclusiveContext *cx, HandleObject obj, uint32_t index, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
extern JSBool
@ -246,7 +230,8 @@ class JSObject : public js::ObjectImpl
* Update the last property, keeping the number of allocated slots in sync
* with the object's new slot span.
*/
static bool setLastProperty(JSContext *cx, JS::HandleObject obj, js::HandleShape shape);
static bool setLastProperty(js::ExclusiveContext *cx,
JS::HandleObject obj, js::HandleShape shape);
/* As above, but does not change the slot span. */
inline void setLastPropertyInfallible(js::Shape *shape);
@ -255,7 +240,7 @@ class JSObject : public js::ObjectImpl
* Make a non-array object with the specified initial state. This method
* takes ownership of any extantSlots it is passed.
*/
static inline JSObject *create(JSContext *cx,
static inline JSObject *create(js::ExclusiveContext *cx,
js::gc::AllocKind kind,
js::gc::InitialHeap heap,
js::HandleShape shape,
@ -263,32 +248,32 @@ class JSObject : public js::ObjectImpl
js::HeapSlot *extantSlots = NULL);
/* Make an array object with the specified initial state. */
static inline JSObject *createArray(JSContext *cx,
js::gc::AllocKind kind,
js::gc::InitialHeap heap,
js::HandleShape shape,
js::HandleTypeObject type,
uint32_t length);
static inline js::ArrayObject *createArray(js::ExclusiveContext *cx,
js::gc::AllocKind kind,
js::gc::InitialHeap heap,
js::HandleShape shape,
js::HandleTypeObject type,
uint32_t length);
/*
* Remove the last property of an object, provided that it is safe to do so
* (the shape and previous shape do not carry conflicting information about
* the object itself).
*/
inline void removeLastProperty(JSContext *cx);
inline void removeLastProperty(js::ExclusiveContext *cx);
inline bool canRemoveLastProperty();
/*
* Update the slot span directly for a dictionary object, and allocate
* slots to cover the new span if necessary.
*/
static bool setSlotSpan(JSContext *cx, JS::HandleObject obj, uint32_t span);
static bool setSlotSpan(js::ExclusiveContext *cx, JS::HandleObject obj, uint32_t span);
/* Upper bound on the number of elements in an object. */
static const uint32_t NELEMENTS_LIMIT = JS_BIT(28);
public:
bool setDelegate(JSContext *cx) {
bool setDelegate(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
}
@ -301,13 +286,13 @@ class JSObject : public js::ObjectImpl
bool watched() const {
return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED);
}
bool setWatched(JSContext *cx) {
bool setWatched(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
}
/* See StackFrame::varObj. */
inline bool isVarObj();
bool setVarObj(JSContext *cx) {
bool setVarObj(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::VAROBJ);
}
@ -320,7 +305,7 @@ class JSObject : public js::ObjectImpl
bool hasUncacheableProto() const {
return lastProperty()->hasObjectFlag(js::BaseShape::UNCACHEABLE_PROTO);
}
bool setUncacheableProto(JSContext *cx) {
bool setUncacheableProto(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE);
}
@ -331,7 +316,7 @@ class JSObject : public js::ObjectImpl
bool hadElementsAccess() const {
return lastProperty()->hasObjectFlag(js::BaseShape::HAD_ELEMENTS_ACCESS);
}
bool setHadElementsAccess(JSContext *cx) {
bool setHadElementsAccess(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::HAD_ELEMENTS_ACCESS);
}
@ -340,7 +325,7 @@ class JSObject : public js::ObjectImpl
return lastProperty()->isEmptyShape();
}
bool shadowingShapeChange(JSContext *cx, const js::Shape &shape);
bool shadowingShapeChange(js::ExclusiveContext *cx, const js::Shape &shape);
/*
* Whether there may be indexed properties on this object, excluding any in
@ -384,16 +369,16 @@ class JSObject : public js::ObjectImpl
* The number of allocated slots is not stored explicitly, and changes to
* the slots must track changes in the slot span.
*/
static bool growSlots(JSContext *cx, js::HandleObject obj, uint32_t oldCount,
static bool growSlots(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t oldCount,
uint32_t newCount);
static void shrinkSlots(JSContext *cx, js::HandleObject obj, uint32_t oldCount,
static void shrinkSlots(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t oldCount,
uint32_t newCount);
bool hasDynamicSlots() const { return slots != NULL; }
protected:
static inline bool updateSlotsForSpan(JSContext *cx, js::HandleObject obj, size_t oldSpan,
size_t newSpan);
static inline bool updateSlotsForSpan(js::ExclusiveContext *cx,
js::HandleObject obj, size_t oldSpan, size_t newSpan);
public:
/*
@ -406,7 +391,8 @@ class JSObject : public js::ObjectImpl
void rollbackProperties(JSContext *cx, uint32_t slotSpan);
inline void nativeSetSlot(uint32_t slot, const js::Value &value);
static inline void nativeSetSlotWithType(JSContext *cx, js::HandleObject, js::Shape *shape,
static inline void nativeSetSlotWithType(js::ExclusiveContext *cx,
js::HandleObject, js::Shape *shape,
const js::Value &value);
inline const js::Value &getReservedSlot(uint32_t index) const {
@ -426,7 +412,7 @@ class JSObject : public js::ObjectImpl
* Marks this object as having a singleton type, and leave the type lazy.
* Constructs a new, unique shape for the object.
*/
static inline bool setSingletonType(JSContext *cx, js::HandleObject obj);
static inline bool setSingletonType(js::ExclusiveContext *cx, js::HandleObject obj);
// uninlinedGetType() is the same as getType(), but not inlined.
inline js::types::TypeObject* getType(JSContext *cx);
@ -461,8 +447,6 @@ class JSObject : public js::ObjectImpl
inline void setType(js::types::TypeObject *newType);
void uninlinedSetType(js::types::TypeObject *newType);
js::types::TypeObject *getNewType(JSContext *cx, js::Class *clasp, JSFunction *fun = NULL);
#ifdef DEBUG
bool hasNewType(js::Class *clasp, js::types::TypeObject *newType);
#endif
@ -472,7 +456,7 @@ class JSObject : public js::ObjectImpl
* to recover this information in the object's type information after it
* is purged on GC.
*/
bool setIteratedSingleton(JSContext *cx) {
bool setIteratedSingleton(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::ITERATED_SINGLETON);
}
@ -578,9 +562,9 @@ class JSObject : public js::ObjectImpl
static const char *className(JSContext *cx, js::HandleObject obj);
/* Accessors for elements. */
inline bool ensureElements(JSContext *cx, uint32_t capacity);
inline bool ensureElements(js::ThreadSafeContext *cx, uint32_t capacity);
bool growElements(js::ThreadSafeContext *tcx, uint32_t newcap);
void shrinkElements(JSContext *cx, uint32_t cap);
void shrinkElements(js::ThreadSafeContext *cx, uint32_t cap);
void setDynamicElements(js::ObjectElements *header) {
JS_ASSERT(!hasDynamicElements());
elements = header->elements();
@ -594,17 +578,19 @@ class JSObject : public js::ObjectImpl
}
inline void setDenseInitializedLength(uint32_t length);
inline void ensureDenseInitializedLength(JSContext *cx, uint32_t index, uint32_t extra);
inline void ensureDenseInitializedLength(js::ExclusiveContext *cx,
uint32_t index, uint32_t extra);
inline void setDenseElement(uint32_t index, const js::Value &val);
inline void initDenseElement(uint32_t index, const js::Value &val);
inline void setDenseElementMaybeConvertDouble(uint32_t index, const js::Value &val);
static inline void setDenseElementWithType(JSContext *cx, js::HandleObject obj,
static inline void setDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj,
uint32_t index, const js::Value &val);
static inline void initDenseElementWithType(JSContext *cx, js::HandleObject obj,
static inline void initDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj,
uint32_t index, const js::Value &val);
static inline void setDenseElementHole(JSContext *cx, js::HandleObject obj, uint32_t index);
static inline void removeDenseElementForSparseIndex(JSContext *cx, js::HandleObject obj,
uint32_t index);
static inline void setDenseElementHole(js::ExclusiveContext *cx,
js::HandleObject obj, uint32_t index);
static inline void removeDenseElementForSparseIndex(js::ExclusiveContext *cx,
js::HandleObject obj, uint32_t index);
inline void copyDenseElements(uint32_t dstStart, const js::Value *src, uint32_t count);
inline void initDenseElements(uint32_t dstStart, const js::Value *src, uint32_t count);
inline void moveDenseElements(uint32_t dstStart, uint32_t srcStart, uint32_t count);
@ -618,7 +604,7 @@ class JSObject : public js::ObjectImpl
inline void setShouldConvertDoubleElements();
/* Packed information for this object's elements. */
inline void markDenseElementsNotPacked(JSContext *cx);
inline void markDenseElementsNotPacked(js::ExclusiveContext *cx);
/*
* ensureDenseElements ensures that the object can hold at least
@ -628,7 +614,8 @@ class JSObject : public js::ObjectImpl
* two cases the object is kept intact.
*/
enum EnsureDenseResult { ED_OK, ED_FAILED, ED_SPARSE };
inline EnsureDenseResult ensureDenseElements(JSContext *cx, uint32_t index, uint32_t extra);
inline EnsureDenseResult ensureDenseElements(js::ExclusiveContext *cx,
uint32_t index, uint32_t extra);
inline EnsureDenseResult parExtendDenseElements(js::ThreadSafeContext *tcx, js::Value *v,
uint32_t extra);
@ -636,10 +623,11 @@ class JSObject : public js::ObjectImpl
uint32_t requiredCapacity, uint32_t extra);
/* Convert a single dense element to a sparse property. */
static bool sparsifyDenseElement(JSContext *cx, js::HandleObject obj, uint32_t index);
static bool sparsifyDenseElement(js::ExclusiveContext *cx,
js::HandleObject obj, uint32_t index);
/* Convert all dense elements to sparse properties. */
static bool sparsifyDenseElements(JSContext *cx, js::HandleObject obj);
static bool sparsifyDenseElements(js::ExclusiveContext *cx, js::HandleObject obj);
/* Small objects are dense, no matter what. */
static const uint32_t MIN_SPARSE_INDEX = 1000;
@ -660,7 +648,7 @@ class JSObject : public js::ObjectImpl
* After adding a sparse index to obj, see if it should be converted to use
* dense elements.
*/
static EnsureDenseResult maybeDensifySparseElements(JSContext *cx, js::HandleObject obj);
static EnsureDenseResult maybeDensifySparseElements(js::ExclusiveContext *cx, js::HandleObject obj);
public:
/*
@ -689,7 +677,7 @@ class JSObject : public js::ObjectImpl
* after calling object-parameter-free shape methods, avoiding coupling
* logic across the object vs. shape module wall.
*/
static bool allocSlot(JSContext *cx, JS::HandleObject obj, uint32_t *slotp);
static bool allocSlot(js::ExclusiveContext *cx, JS::HandleObject obj, uint32_t *slotp);
void freeSlot(uint32_t slot);
public:
@ -707,8 +695,8 @@ class JSObject : public js::ObjectImpl
js::MutableHandleValue vp);
private:
static js::Shape *getChildProperty(JSContext *cx, JS::HandleObject obj,
js::HandleShape parent, js::StackShape &child);
static js::Shape *getChildProperty(js::ExclusiveContext *cx, JS::HandleObject obj,
js::HandleShape parent, js::StackShape &child);
protected:
/*
@ -718,12 +706,12 @@ class JSObject : public js::ObjectImpl
* 1. getter and setter must be normalized based on flags (see jsscope.cpp).
* 2. Checks for non-extensibility must be done by callers.
*/
static js::Shape *addPropertyInternal(JSContext *cx,
JS::HandleObject obj, JS::HandleId id,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, int shortid, js::Shape **spp,
bool allowDictionary);
static js::Shape *addPropertyInternal(js::ExclusiveContext *cx,
JS::HandleObject obj, JS::HandleId id,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, int shortid, js::Shape **spp,
bool allowDictionary);
private:
struct TradeGutsReserved;
@ -735,67 +723,44 @@ class JSObject : public js::ObjectImpl
public:
/* Add a property whose id is not yet in this scope. */
static js::Shape *addProperty(JSContext *cx, JS::HandleObject, JS::HandleId id,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs, unsigned flags,
int shortid, bool allowDictionary = true);
static js::Shape *addProperty(js::ExclusiveContext *cx, JS::HandleObject, JS::HandleId id,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs, unsigned flags,
int shortid, bool allowDictionary = true);
/* Add a data property whose id is not yet in this scope. */
js::Shape *addDataProperty(JSContext *cx, jsid id_, uint32_t slot, unsigned attrs) {
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
JS::RootedObject self(cx, this);
JS::RootedId id(cx, id_);
return addProperty(cx, self, id, NULL, NULL, slot, attrs, 0, 0);
}
js::Shape *addDataProperty(JSContext *cx, js::HandlePropertyName name, uint32_t slot, unsigned attrs) {
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
JS::RootedObject self(cx, this);
JS::RootedId id(cx, NameToId(name));
return addProperty(cx, self, id, NULL, NULL, slot, attrs, 0, 0);
}
js::Shape *addDataProperty(js::ExclusiveContext *cx,
jsid id_, uint32_t slot, unsigned attrs);
js::Shape *addDataProperty(js::ExclusiveContext *cx, js::HandlePropertyName name,
uint32_t slot, unsigned attrs);
/* Add or overwrite a property for id in this scope. */
static js::Shape *putProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, int shortid);
static js::Shape *putProperty(JSContext *cx, JS::HandleObject obj,
js::PropertyName *name,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, int shortid)
{
JS::RootedId id(cx, js::NameToId(name));
return putProperty(cx, obj, id, getter, setter, slot, attrs, flags, shortid);
}
static js::Shape *putProperty(js::ExclusiveContext *cx, JS::HandleObject obj, JS::HandleId id,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, int shortid);
static inline js::Shape *putProperty(js::ExclusiveContext *cx, JS::HandleObject obj,
js::PropertyName *name,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, int shortid);
/* Change the given property into a sibling with the same id in this scope. */
static js::Shape *changeProperty(JSContext *cx, js::HandleObject obj,
js::HandleShape shape, unsigned attrs, unsigned mask,
JSPropertyOp getter, JSStrictPropertyOp setter);
static js::Shape *changeProperty(js::ExclusiveContext *cx, js::HandleObject obj,
js::HandleShape shape, unsigned attrs, unsigned mask,
JSPropertyOp getter, JSStrictPropertyOp setter);
static inline bool changePropertyAttributes(JSContext *cx, js::HandleObject obj,
js::HandleShape shape, unsigned attrs);
/* Remove the property named by id from this object. */
bool removeProperty(JSContext *cx, jsid id);
bool removeProperty(js::ExclusiveContext *cx, jsid id);
/* Clear the scope, making it empty. */
static void clear(JSContext *cx, js::HandleObject obj);
static JSBool lookupGeneric(JSContext *cx, js::HandleObject obj, js::HandleId id,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
/* NB: The logic of lookupGeneric is implicitly reflected in IonBuilder.cpp's
* |CanEffectlesslyCallLookupGenericOnObject| logic.
* If this changes, please remember to update the logic there as well.
*/
js::LookupGenericOp op = obj->getOps()->lookupGeneric;
if (op)
return op(cx, obj, id, objp, propp);
return js::baseops::LookupProperty<js::CanGC>(cx, obj, id, objp, propp);
}
js::MutableHandleObject objp, js::MutableHandleShape propp);
static JSBool lookupProperty(JSContext *cx, js::HandleObject obj, js::PropertyName *name,
js::MutableHandleObject objp, js::MutableHandleShape propp)
@ -818,46 +783,29 @@ class JSObject : public js::ObjectImpl
return lookupGeneric(cx, obj, id, objp, propp);
}
static JSBool defineGeneric(JSContext *cx, js::HandleObject obj,
js::HandleId id, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE)
{
JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
js::DefineGenericOp op = obj->getOps()->defineGeneric;
return (op ? op : js::baseops::DefineGeneric)(cx, obj, id, value, getter, setter, attrs);
}
static JSBool defineGeneric(js::ExclusiveContext *cx, js::HandleObject obj,
js::HandleId id, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE);
static JSBool defineProperty(JSContext *cx, js::HandleObject obj,
static JSBool defineProperty(js::ExclusiveContext *cx, js::HandleObject obj,
js::PropertyName *name, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE)
{
JS::RootedId id(cx, js::NameToId(name));
return defineGeneric(cx, obj, id, value, getter, setter, attrs);
}
unsigned attrs = JSPROP_ENUMERATE);
static JSBool defineElement(JSContext *cx, js::HandleObject obj,
static JSBool defineElement(js::ExclusiveContext *cx, js::HandleObject obj,
uint32_t index, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE)
{
js::DefineElementOp op = obj->getOps()->defineElement;
return (op ? op : js::baseops::DefineElement)(cx, obj, index, value, getter, setter, attrs);
}
unsigned attrs = JSPROP_ENUMERATE);
static JSBool defineSpecial(JSContext *cx, js::HandleObject obj,
static JSBool defineSpecial(js::ExclusiveContext *cx, js::HandleObject obj,
js::SpecialId sid, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return defineGeneric(cx, obj, id, value, getter, setter, attrs);
}
unsigned attrs = JSPROP_ENUMERATE);
static JSBool getGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::HandleId id, js::MutableHandleValue vp)
@ -1201,7 +1149,7 @@ js_PopulateObject(JSContext *cx, js::HandleObject newborn, js::HandleObject prop
* Fast access to immutable standard objects (constructors and prototypes).
*/
extern bool
js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
js_GetClassObject(js::ExclusiveContext *cx, JSObject *obj, JSProtoKey key,
js::MutableHandleObject objp);
/*
@ -1216,7 +1164,7 @@ js_IdentifyClassPrototype(JSObject *obj);
* JSProto_Null, clasp must non-null.
*/
bool
js_FindClassObject(JSContext *cx, JSProtoKey protoKey, js::MutableHandleValue vp,
js_FindClassObject(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleValue vp,
js::Class *clasp = NULL);
/*
@ -1306,35 +1254,17 @@ const unsigned DNP_SKIP_TYPE = 4; /* Don't update type information */
* Return successfully added or changed shape or NULL on error.
*/
extern bool
DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow = 0);
inline bool
DefineNativeProperty(JSContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow = 0)
{
Rooted<jsid> id(cx, NameToId(name));
return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, flags,
shortid, defineHow);
}
/*
* Specialized subroutine that allows caller to preset JSRESOLVE_* flags.
*/
extern bool
LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
LookupPropertyWithFlags(ExclusiveContext *cx, HandleObject obj, HandleId id, unsigned flags,
js::MutableHandleObject objp, js::MutableHandleShape propp);
inline bool
LookupPropertyWithFlags(JSContext *cx, HandleObject obj, PropertyName *name, unsigned flags,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
Rooted<jsid> id(cx, NameToId(name));
return LookupPropertyWithFlags(cx, obj, id, flags, objp, propp);
}
/*
* Call the [[DefineOwnProperty]] internal method of obj.
*
@ -1527,7 +1457,7 @@ js_InferFlags(JSContext *cx, unsigned defaultFlags);
* methods instead.
*/
extern bool
js_GetClassPrototype(JSContext *cx, JSProtoKey protoKey, js::MutableHandleObject protop,
js_GetClassPrototype(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleObject protop,
js::Class *clasp = NULL);
namespace js {

View File

@ -131,7 +131,7 @@ JSObject::setLastPropertyInfallible(js::Shape *shape)
}
inline void
JSObject::removeLastProperty(JSContext *cx)
JSObject::removeLastProperty(js::ExclusiveContext *cx)
{
JS_ASSERT(canRemoveLastProperty());
JS::RootedObject self(cx, this);
@ -202,7 +202,7 @@ JSObject::setShouldConvertDoubleElements()
}
inline bool
JSObject::ensureElements(JSContext *cx, uint32_t capacity)
JSObject::ensureElements(js::ThreadSafeContext *cx, uint32_t capacity)
{
if (capacity > getDenseCapacity())
return growElements(cx, capacity);
@ -233,7 +233,7 @@ JSObject::initDenseElement(uint32_t index, const js::Value &val)
}
/* static */ inline void
JSObject::setDenseElementWithType(JSContext *cx, js::HandleObject obj, uint32_t index,
JSObject::setDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index,
const js::Value &val)
{
js::types::AddTypePropertyId(cx, obj, JSID_VOID, val);
@ -241,7 +241,7 @@ JSObject::setDenseElementWithType(JSContext *cx, js::HandleObject obj, uint32_t
}
/* static */ inline void
JSObject::initDenseElementWithType(JSContext *cx, js::HandleObject obj, uint32_t index,
JSObject::initDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index,
const js::Value &val)
{
JS_ASSERT(!obj->shouldConvertDoubleElements());
@ -250,14 +250,15 @@ JSObject::initDenseElementWithType(JSContext *cx, js::HandleObject obj, uint32_t
}
/* static */ inline void
JSObject::setDenseElementHole(JSContext *cx, js::HandleObject obj, uint32_t index)
JSObject::setDenseElementHole(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index)
{
js::types::MarkTypeObjectFlags(cx, obj, js::types::OBJECT_FLAG_NON_PACKED);
obj->setDenseElement(index, js::MagicValue(JS_ELEMENTS_HOLE));
}
/* static */ inline void
JSObject::removeDenseElementForSparseIndex(JSContext *cx, js::HandleObject obj, uint32_t index)
JSObject::removeDenseElementForSparseIndex(js::ExclusiveContext *cx,
js::HandleObject obj, uint32_t index)
{
js::types::MarkTypeObjectFlags(cx, obj,
js::types::OBJECT_FLAG_NON_PACKED |
@ -333,14 +334,14 @@ JSObject::moveDenseElementsUnbarriered(uint32_t dstStart, uint32_t srcStart, uin
}
inline void
JSObject::markDenseElementsNotPacked(JSContext *cx)
JSObject::markDenseElementsNotPacked(js::ExclusiveContext *cx)
{
JS_ASSERT(isNative());
MarkTypeObjectFlags(cx, this, js::types::OBJECT_FLAG_NON_PACKED);
}
inline void
JSObject::ensureDenseInitializedLength(JSContext *cx, uint32_t index, uint32_t extra)
JSObject::ensureDenseInitializedLength(js::ExclusiveContext *cx, uint32_t index, uint32_t extra)
{
/*
* Ensure that the array's contents have been initialized up to index, and
@ -439,7 +440,7 @@ JSObject::parExtendDenseElements(js::ThreadSafeContext *tcx, js::Value *v, uint3
}
inline JSObject::EnsureDenseResult
JSObject::ensureDenseElements(JSContext *cx, uint32_t index, uint32_t extra)
JSObject::ensureDenseElements(js::ExclusiveContext *cx, uint32_t index, uint32_t extra)
{
JS_ASSERT(isNative());
@ -478,13 +479,15 @@ JSObject::ensureDenseElements(JSContext *cx, uint32_t index, uint32_t extra)
}
/* static */ inline bool
JSObject::setSingletonType(JSContext *cx, js::HandleObject obj)
JSObject::setSingletonType(js::ExclusiveContext *cxArg, js::HandleObject obj)
{
JS_ASSERT(!IsInsideNursery(cx->runtime(), obj.get()));
if (!cx->typeInferenceEnabled())
if (!cxArg->typeInferenceEnabled())
return true;
JSContext *cx = cxArg->asJSContext();
JS_ASSERT(!IsInsideNursery(cx->runtime(), obj.get()));
js::types::TypeObject *type =
cx->compartment()->getLazyType(cx, obj->getClass(), obj->getTaggedProto());
if (!type)
@ -513,7 +516,7 @@ JSObject::clearType(JSContext *cx, js::HandleObject obj)
JS_ASSERT(!obj->hasSingletonType());
JS_ASSERT(cx->compartment() == obj->compartment());
js::types::TypeObject *type = cx->compartment()->getNewType(cx, obj->getClass(), NULL);
js::types::TypeObject *type = cx->getNewType(obj->getClass(), NULL);
if (!type)
return false;
@ -551,7 +554,7 @@ inline bool JSObject::isVarObj()
}
/* static */ inline JSObject *
JSObject::create(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
js::HandleShape shape, js::HandleTypeObject type,
js::HeapSlot *extantSlots /* = NULL */)
{
@ -586,7 +589,8 @@ JSObject::create(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap
}
#ifdef JSGC_GENERATIONAL
cx->runtime()->gcNursery.notifyInitialSlots(obj, slots);
if (heap != js::gc::TenuredHeap)
cx->asJSContext()->runtime()->gcNursery.notifyInitialSlots(obj, slots);
#endif
obj->shape_.init(shape);
@ -605,8 +609,8 @@ JSObject::create(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap
return obj;
}
/* static */ inline JSObject *
JSObject::createArray(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
/* static */ inline js::ArrayObject *
JSObject::createArray(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
js::HandleShape shape, js::HandleTypeObject type,
uint32_t length)
{
@ -631,10 +635,8 @@ JSObject::createArray(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap
uint32_t capacity = js::gc::GetGCKindSlots(kind) - js::ObjectElements::VALUES_PER_HEADER;
JSObject *obj = js_NewGCObject<js::CanGC>(cx, kind, heap);
if (!obj) {
js_ReportOutOfMemory(cx);
if (!obj)
return NULL;
}
obj->shape_.init(shape);
obj->type_.init(type);
@ -642,7 +644,7 @@ JSObject::createArray(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap
obj->setFixedElements();
new (obj->getElementsHeader()) js::ObjectElements(capacity, length);
return obj;
return &obj->as<js::ArrayObject>();
}
inline void
@ -683,7 +685,7 @@ JSObject::nativeSetSlot(uint32_t slot, const js::Value &value)
}
/* static */ inline void
JSObject::nativeSetSlotWithType(JSContext *cx, js::HandleObject obj, js::Shape *shape,
JSObject::nativeSetSlotWithType(js::ExclusiveContext *cx, js::HandleObject obj, js::Shape *shape,
const js::Value &value)
{
obj->nativeSetSlot(shape->slot(), value);
@ -977,11 +979,11 @@ class AutoPropertyDescriptorRooter : private AutoGCRooter, public PropertyDescri
* default to the prototype's global if the prototype is non-null.
*/
JSObject *
NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, TaggedProto proto, JSObject *parent,
NewObjectWithGivenProto(ExclusiveContext *cx, js::Class *clasp, TaggedProto proto, JSObject *parent,
gc::AllocKind allocKind, NewObjectKind newKind);
inline JSObject *
NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, TaggedProto proto, JSObject *parent,
NewObjectWithGivenProto(ExclusiveContext *cx, js::Class *clasp, TaggedProto proto, JSObject *parent,
NewObjectKind newKind = GenericObject)
{
gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
@ -989,7 +991,7 @@ NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, TaggedProto proto, JSOb
}
inline JSObject *
NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
NewObjectWithGivenProto(ExclusiveContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
NewObjectKind newKind = GenericObject)
{
return NewObjectWithGivenProto(cx, clasp, TaggedProto(proto), parent, newKind);
@ -1007,7 +1009,7 @@ GetClassProtoKey(js::Class *clasp)
}
inline bool
FindProto(JSContext *cx, js::Class *clasp, MutableHandleObject proto)
FindProto(ExclusiveContext *cx, js::Class *clasp, MutableHandleObject proto)
{
JSProtoKey protoKey = GetClassProtoKey(clasp);
if (!js_GetClassPrototype(cx, protoKey, proto, clasp))
@ -1035,18 +1037,18 @@ FindProto(JSContext *cx, js::Class *clasp, MutableHandleObject proto)
* parent will be that global.
*/
JSObject *
NewObjectWithClassProtoCommon(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
NewObjectWithClassProtoCommon(ExclusiveContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
gc::AllocKind allocKind, NewObjectKind newKind);
inline JSObject *
NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
NewObjectWithClassProto(ExclusiveContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
gc::AllocKind allocKind, NewObjectKind newKind = GenericObject)
{
return NewObjectWithClassProtoCommon(cx, clasp, proto, parent, allocKind, newKind);
}
inline JSObject *
NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
NewObjectWithClassProto(ExclusiveContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
NewObjectKind newKind = GenericObject)
{
gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
@ -1058,14 +1060,14 @@ NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObje
* according to the context's active global.
*/
inline JSObject *
NewBuiltinClassInstance(JSContext *cx, Class *clasp, gc::AllocKind allocKind,
NewBuiltinClassInstance(ExclusiveContext *cx, Class *clasp, gc::AllocKind allocKind,
NewObjectKind newKind = GenericObject)
{
return NewObjectWithClassProto(cx, clasp, NULL, NULL, allocKind, newKind);
}
inline JSObject *
NewBuiltinClassInstance(JSContext *cx, Class *clasp, NewObjectKind newKind = GenericObject)
NewBuiltinClassInstance(ExclusiveContext *cx, Class *clasp, NewObjectKind newKind = GenericObject)
{
gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
return NewBuiltinClassInstance(cx, clasp, allocKind, newKind);
@ -1202,20 +1204,60 @@ DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, H
gc::AllocKind ctorKind = JSFunction::FinalizeKind);
static JS_ALWAYS_INLINE bool
NewObjectMetadata(JSContext *cx, JSObject **pmetadata)
NewObjectMetadata(ExclusiveContext *cxArg, JSObject **pmetadata)
{
// The metadata callback is invoked before each created object, except when
// analysis is active as the callback may reenter JS.
JS_ASSERT(!*pmetadata);
if (JS_UNLIKELY((size_t)cx->compartment()->objectMetadataCallback) &&
!cx->compartment()->activeAnalysis)
{
gc::AutoSuppressGC suppress(cx);
return cx->compartment()->objectMetadataCallback(cx, pmetadata);
if (JSContext *cx = cxArg->maybeJSContext()) {
if (JS_UNLIKELY((size_t)cx->compartment()->objectMetadataCallback) &&
!cx->compartment()->activeAnalysis)
{
gc::AutoSuppressGC suppress(cx);
return cx->compartment()->objectMetadataCallback(cx, pmetadata);
}
}
return true;
}
inline bool
DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow = 0)
{
Rooted<jsid> id(cx, NameToId(name));
return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, flags,
shortid, defineHow);
}
inline bool
LookupPropertyWithFlags(ExclusiveContext *cx, HandleObject obj, PropertyName *name, unsigned flags,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
Rooted<jsid> id(cx, NameToId(name));
return LookupPropertyWithFlags(cx, obj, id, flags, objp, propp);
}
namespace baseops {
inline bool
LookupProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name,
MutableHandleObject objp, MutableHandleShape propp)
{
Rooted<jsid> id(cx, NameToId(name));
return LookupProperty<CanGC>(cx, obj, id, objp, propp);
}
inline JSBool
DefineProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
Rooted<jsid> id(cx, NameToId(name));
return DefineGeneric(cx, obj, id, value, getter, setter, attrs);
}
} /* namespace baseops */
} /* namespace js */
extern JSObject *

View File

@ -25,6 +25,7 @@
#include "jsatominlines.h"
#include "jsboolinlines.h"
#include "jsstrinlines.h"
using namespace js;
using namespace js::gc;

View File

@ -491,7 +491,7 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
: JSID_TO_ATOM(shape->propid());
JSAutoByteString bytes;
if (!js_AtomToPrintableString(cx, atom, &bytes))
if (!AtomToPrintableString(cx, atom, &bytes))
return false;
r.popFront();

View File

@ -32,11 +32,11 @@ ShapeHasher::match(const Key k, const Lookup &l)
}
Shape *
PropertyTree::newShape(JSContext *cx)
PropertyTree::newShape(ExclusiveContext *cx)
{
Shape *shape = js_NewGCShape(cx);
if (!shape)
JS_ReportOutOfMemory(cx);
js_ReportOutOfMemory(cx);
return shape;
}
@ -55,13 +55,13 @@ HashChildren(Shape *kid1, Shape *kid2)
}
bool
PropertyTree::insertChild(JSContext *cx, Shape *parent, Shape *child)
PropertyTree::insertChild(ExclusiveContext *cx, Shape *parent, Shape *child)
{
JS_ASSERT(!parent->inDictionary());
JS_ASSERT(!child->parent);
JS_ASSERT(!child->inDictionary());
JS_ASSERT(cx->compartment() == compartment);
JS_ASSERT(child->compartment() == parent->compartment());
JS_ASSERT(cx->isInsideCurrentCompartment(this));
KidsPointer *kidp = &parent->kids;
@ -78,7 +78,7 @@ PropertyTree::insertChild(JSContext *cx, Shape *parent, Shape *child)
KidsHash *hash = HashChildren(shape, child);
if (!hash) {
JS_ReportOutOfMemory(cx);
js_ReportOutOfMemory(cx);
return false;
}
kidp->setHash(hash);
@ -87,7 +87,7 @@ PropertyTree::insertChild(JSContext *cx, Shape *parent, Shape *child)
}
if (!kidp->toHash()->putNew(child, child)) {
JS_ReportOutOfMemory(cx);
js_ReportOutOfMemory(cx);
return false;
}
@ -127,7 +127,7 @@ Shape::removeChild(Shape *child)
}
Shape *
PropertyTree::getChild(JSContext *cx, Shape *parent_, uint32_t nfixed, const StackShape &child)
PropertyTree::getChild(ExclusiveContext *cx, Shape *parent_, uint32_t nfixed, const StackShape &child)
{
{
Shape *shape = NULL;

View File

@ -72,9 +72,9 @@ class PropertyTree
{
friend class ::JSFunction;
JSCompartment *compartment;
JSCompartment *compartment_;
bool insertChild(JSContext *cx, Shape *parent, Shape *child);
bool insertChild(ExclusiveContext *cx, Shape *parent, Shape *child);
PropertyTree();
@ -90,12 +90,14 @@ class PropertyTree
};
PropertyTree(JSCompartment *comp)
: compartment(comp)
: compartment_(comp)
{
}
Shape *newShape(JSContext *cx);
Shape *getChild(JSContext *cx, Shape *parent, uint32_t nfixed, const StackShape &child);
JSCompartment *compartment() { return compartment_; }
Shape *newShape(ExclusiveContext *cx);
Shape *getChild(ExclusiveContext *cx, Shape *parent, uint32_t nfixed, const StackShape &child);
#ifdef DEBUG
static void dumpShapes(JSRuntime *rt);

View File

@ -832,7 +832,7 @@ ReturnedValueMustNotBePrimitive(JSContext *cx, HandleObject proxy, JSAtom *atom,
{
if (v.isPrimitive()) {
JSAutoByteString bytes;
if (js_AtomToPrintableString(cx, atom, &bytes)) {
if (AtomToPrintableString(cx, atom, &bytes)) {
RootedValue val(cx, ObjectOrNullValue(proxy));
js_ReportValueError2(cx, JSMSG_BAD_TRAP_RETURN_VALUE,
JSDVG_SEARCH_STACK, val, NullPtr(), bytes.ptr());
@ -1546,7 +1546,7 @@ ReportInvalidTrapResult(JSContext *cx, JSObject *proxy, JSAtom *atom)
{
RootedValue v(cx, ObjectOrNullValue(proxy));
JSAutoByteString bytes;
if (!js_AtomToPrintableString(cx, atom, &bytes))
if (!AtomToPrintableString(cx, atom, &bytes))
return;
js_ReportValueError2(cx, JSMSG_INVALID_TRAP_RESULT, JSDVG_IGNORE_STACK, v,
NullPtr(), bytes.ptr());
@ -1882,7 +1882,7 @@ ScriptedDirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdV
// step f
if (trapResult.isPrimitive()) {
JSAutoByteString bytes;
if (!js_AtomToPrintableString(cx, cx->names().enumerate, &bytes))
if (!AtomToPrintableString(cx, cx->names().enumerate, &bytes))
return false;
RootedValue v(cx, ObjectOrNullValue(proxy));
js_ReportValueError2(cx, JSMSG_INVALID_TRAP_RESULT, JSDVG_SEARCH_STACK,
@ -2202,7 +2202,7 @@ ScriptedDirectProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector
// step f
if (trapResult.isPrimitive()) {
JSAutoByteString bytes;
if (!js_AtomToPrintableString(cx, cx->names().keys, &bytes))
if (!AtomToPrintableString(cx, cx->names().keys, &bytes))
return false;
RootedValue v(cx, ObjectOrNullValue(proxy));
js_ReportValueError2(cx, JSMSG_INVALID_TRAP_RESULT, JSDVG_IGNORE_STACK,
@ -3379,7 +3379,7 @@ proxy(JSContext *cx, unsigned argc, jsval *vp)
RootedObject proto(cx);
if (!JSObject::getProto(cx, target, &proto))
return false;
RootedObject fun(cx, target->isCallable() ? target : (JSObject *) NULL);
RootedObject fun(cx, target->isCallable() ? target.get() : (JSObject *) NULL);
RootedValue priv(cx, ObjectValue(*target));
JSObject *proxy = NewProxyObject(cx, &ScriptedDirectProxyHandler::singleton,
priv, proto, cx->global(),

View File

@ -14,6 +14,8 @@
#include "jsprototypes.h"
#include "jstypes.h"
#include "mozilla/PodOperations.h"
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING) || defined(DEBUG)
# define JSGC_TRACK_EXACT_ROOTS
#endif
@ -29,6 +31,8 @@ class Value;
template <typename T>
class Rooted;
class AutoGCRooter;
struct Zone;
} /* namespace JS */
@ -231,6 +235,7 @@ struct Runtime
namespace js {
struct ThreadSafeContext;
class ExclusiveContext;
class Allocator;
@ -289,8 +294,15 @@ struct ContextFriendFields
public:
explicit ContextFriendFields(JSRuntime *rt)
: runtime_(rt), compartment_(NULL), zone_(NULL)
{ }
: runtime_(rt), compartment_(NULL), zone_(NULL), autoGCRooters(NULL)
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
mozilla::PodArrayZero(thingGCRooters);
#endif
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
skipGCRooters = NULL;
#endif
}
static const ContextFriendFields *get(const JSContext *cx) {
return reinterpret_cast<const ContextFriendFields *>(cx);
@ -320,6 +332,9 @@ struct ContextFriendFields
SkipRoot *skipGCRooters;
#endif
/* Stack of thread-stack-allocated GC roots. */
JS::AutoGCRooter *autoGCRooters;
friend JSRuntime *GetRuntime(const JSContext *cx);
friend JSCompartment *GetContextCompartment(const JSContext *cx);
friend JS::Zone *GetContextZone(const JSContext *cx);

View File

@ -25,6 +25,7 @@
#include "vm/RegExpObject.h"
#include "jsobjinlines.h"
#include "jsstrinlines.h"
using namespace js;
using namespace js::frontend;
@ -3052,7 +3053,7 @@ reflect_parse(JSContext *cx, uint32_t argc, jsval *vp)
CompileOptions options(cx);
options.setFileAndLine(filename, lineno);
options.setCanLazilyParse(false);
Parser<FullParseHandler> parser(cx, options, chars.get(), length,
Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options, chars.get(), length,
/* foldConstants = */ false, NULL, NULL);
serialize.setParser(&parser);

View File

@ -51,7 +51,7 @@ using mozilla::PodZero;
typedef Rooted<GlobalObject *> RootedGlobalObject;
/* static */ unsigned
Bindings::argumentsVarIndex(JSContext *cx, InternalBindingsHandle bindings)
Bindings::argumentsVarIndex(ExclusiveContext *cx, InternalBindingsHandle bindings)
{
HandlePropertyName arguments = cx->names().arguments;
BindingIter bi(bindings);
@ -61,7 +61,7 @@ Bindings::argumentsVarIndex(JSContext *cx, InternalBindingsHandle bindings)
}
bool
Bindings::initWithTemporaryStorage(JSContext *cx, InternalBindingsHandle self,
Bindings::initWithTemporaryStorage(ExclusiveContext *cx, InternalBindingsHandle self,
unsigned numArgs, unsigned numVars,
Binding *bindingArray)
{
@ -69,10 +69,12 @@ Bindings::initWithTemporaryStorage(JSContext *cx, InternalBindingsHandle self,
JS_ASSERT(self->bindingArrayAndFlag_ == TEMPORARY_STORAGE_BIT);
if (numArgs > UINT16_MAX || numVars > UINT16_MAX) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
self->numArgs_ > self->numVars_ ?
JSMSG_TOO_MANY_FUN_ARGS :
JSMSG_TOO_MANY_LOCALS);
if (cx->isJSContext()) {
JS_ReportErrorNumber(cx->asJSContext(), js_GetErrorMessage, NULL,
self->numArgs_ > self->numVars_ ?
JSMSG_TOO_MANY_FUN_ARGS :
JSMSG_TOO_MANY_LOCALS);
}
return false;
}
@ -119,7 +121,7 @@ Bindings::initWithTemporaryStorage(JSContext *cx, InternalBindingsHandle self,
return false;
#endif
StackBaseShape base(cx->compartment(), &CallObject::class_, cx->global(), NULL,
StackBaseShape base(cx, &CallObject::class_, cx->global(), NULL,
BaseShape::VAROBJ | BaseShape::DELEGATE);
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
@ -1494,7 +1496,7 @@ ScriptSource::sourceMap()
*/
SharedScriptData *
js::SharedScriptData::new_(JSContext *cx, uint32_t codeLength,
js::SharedScriptData::new_(ExclusiveContext *cx, uint32_t codeLength,
uint32_t srcnotesLength, uint32_t natoms)
{
uint32_t baseLength = codeLength + srcnotesLength;
@ -1513,22 +1515,21 @@ js::SharedScriptData::new_(JSContext *cx, uint32_t codeLength,
}
bool
js::SaveSharedScriptData(JSContext *cx, Handle<JSScript *> script, SharedScriptData *ssd)
js::SaveSharedScriptData(ExclusiveContext *cx, Handle<JSScript *> script, SharedScriptData *ssd)
{
ASSERT(script != NULL);
ASSERT(ssd != NULL);
JSRuntime *rt = cx->runtime();
ScriptBytecodeHasher::Lookup l(ssd);
ScriptDataTable::AddPtr p = rt->scriptDataTable.lookupForAdd(l);
ScriptDataTable::AddPtr p = cx->scriptDataTable().lookupForAdd(l);
if (p) {
js_free(ssd);
ssd = *p;
} else {
if (!rt->scriptDataTable.add(p, ssd)) {
if (!cx->scriptDataTable().add(p, ssd)) {
js_free(ssd);
JS_ReportOutOfMemory(cx);
js_ReportOutOfMemory(cx);
return false;
}
}
@ -1540,8 +1541,11 @@ js::SaveSharedScriptData(JSContext *cx, Handle<JSScript *> script, SharedScriptD
* old scripts or exceptions pointing to the bytecode may no longer be
* reachable. This is effectively a read barrier.
*/
if (JS::IsIncrementalGCInProgress(rt) && rt->gcIsFull)
ssd->marked = true;
if (cx->isJSContext()) {
JSRuntime *rt = cx->asJSContext()->runtime();
if (JS::IsIncrementalGCInProgress(rt) && rt->gcIsFull)
ssd->marked = true;
}
#endif
script->code = ssd->data;
@ -1687,8 +1691,25 @@ ScriptDataSize(uint32_t nbindings, uint32_t nobjects, uint32_t nregexps,
return size;
}
void
JSScript::initCompartmentAndPrincipals(ExclusiveContext *cx, const CompileOptions &options)
{
compartment_ = cx->compartment_;
/* Establish invariant: principals implies originPrincipals. */
if (options.principals) {
JS_ASSERT(options.principals == cx->compartment_->principals);
originPrincipals
= options.originPrincipals ? options.originPrincipals : options.principals;
JS_HoldPrincipals(originPrincipals);
} else if (options.originPrincipals) {
originPrincipals = options.originPrincipals;
JS_HoldPrincipals(originPrincipals);
}
}
JSScript *
JSScript::Create(JSContext *cx, HandleObject enclosingScope, bool savedCallerFun,
JSScript::Create(ExclusiveContext *cx, HandleObject enclosingScope, bool savedCallerFun,
const CompileOptions &options, unsigned staticLevel,
JS::HandleScriptSource sourceObject, uint32_t bufStart, uint32_t bufEnd)
{
@ -1703,18 +1724,7 @@ JSScript::Create(JSContext *cx, HandleObject enclosingScope, bool savedCallerFun
script->enclosingScopeOrOriginalFunction_ = enclosingScope;
script->savedCallerFun = savedCallerFun;
script->compartment_ = cx->compartment();
/* Establish invariant: principals implies originPrincipals. */
if (options.principals) {
JS_ASSERT(options.principals == cx->compartment()->principals);
script->originPrincipals
= options.originPrincipals ? options.originPrincipals : options.principals;
JS_HoldPrincipals(script->originPrincipals);
} else if (options.originPrincipals) {
script->originPrincipals = options.originPrincipals;
JS_HoldPrincipals(script->originPrincipals);
}
script->initCompartmentAndPrincipals(cx, options);
script->compileAndGo = options.compileAndGo;
script->selfHosted = options.selfHostingMode;
@ -1728,7 +1738,10 @@ JSScript::Create(JSContext *cx, HandleObject enclosingScope, bool savedCallerFun
// stack if we nest functions more than a few hundred deep, so this will
// never trigger. Oh well.
if (staticLevel > UINT16_MAX) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_DEEP, js_function_str);
if (cx->isJSContext()) {
JS_ReportErrorNumber(cx->asJSContext(),
js_GetErrorMessage, NULL, JSMSG_TOO_DEEP, js_function_str);
}
return NULL;
}
script->staticLevel = uint16_t(staticLevel);
@ -1741,7 +1754,7 @@ JSScript::Create(JSContext *cx, HandleObject enclosingScope, bool savedCallerFun
}
static inline uint8_t *
AllocScriptData(JSContext *cx, size_t size)
AllocScriptData(ExclusiveContext *cx, size_t size)
{
uint8_t *data = static_cast<uint8_t *>(cx->calloc_(JS_ROUNDUP(size, sizeof(Value))));
if (!data)
@ -1753,7 +1766,7 @@ AllocScriptData(JSContext *cx, size_t size)
}
/* static */ bool
JSScript::partiallyInit(JSContext *cx, Handle<JSScript*> script, uint32_t nobjects,
JSScript::partiallyInit(ExclusiveContext *cx, HandleScript script, uint32_t nobjects,
uint32_t nregexps, uint32_t ntrynotes, uint32_t nconsts, uint32_t nTypeSets)
{
size_t size = ScriptDataSize(script->bindings.count(), nobjects, nregexps, ntrynotes, nconsts);
@ -1824,7 +1837,7 @@ JSScript::partiallyInit(JSContext *cx, Handle<JSScript*> script, uint32_t nobjec
}
/* static */ bool
JSScript::fullyInitTrivial(JSContext *cx, Handle<JSScript*> script)
JSScript::fullyInitTrivial(ExclusiveContext *cx, Handle<JSScript*> script)
{
if (!partiallyInit(cx, script, 0, 0, 0, 0, 0))
return false;
@ -1840,7 +1853,7 @@ JSScript::fullyInitTrivial(JSContext *cx, Handle<JSScript*> script)
}
/* static */ bool
JSScript::fullyInitFromEmitter(JSContext *cx, Handle<JSScript*> script, BytecodeEmitter *bce)
JSScript::fullyInitFromEmitter(ExclusiveContext *cx, HandleScript script, BytecodeEmitter *bce)
{
/* The counts of indexed things must be checked during code generation. */
JS_ASSERT(bce->atomIndices->count() <= INDEX_LIMIT);
@ -1874,7 +1887,7 @@ JSScript::fullyInitFromEmitter(JSContext *cx, Handle<JSScript*> script, Bytecode
PodCopy<jsbytecode>(code + prologLength, bce->code().begin(), mainLength);
if (!FinishTakingSrcNotes(cx, bce, (jssrcnote *)(code + script->length)))
return false;
InitAtomMap(cx, bce->atomIndices.getMap(), ssd->atoms(script->length, nsrcnotes));
InitAtomMap(bce->atomIndices.getMap(), ssd->atoms(script->length, nsrcnotes));
if (!SaveSharedScriptData(cx, script, ssd))
return false;
@ -3002,7 +3015,8 @@ LazyScript::sourceObject() const
}
/* static */ LazyScript *
LazyScript::Create(JSContext *cx, uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version,
LazyScript::Create(ExclusiveContext *cx, uint32_t numFreeVariables, uint32_t numInnerFunctions,
JSVersion version,
uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
{
JS_ASSERT(begin <= end);

View File

@ -180,7 +180,7 @@ class Bindings
* storage is release, switchToScriptStorage must be called, providing a
* pointer into the Binding array stored in script->data.
*/
static bool initWithTemporaryStorage(JSContext *cx, InternalBindingsHandle self,
static bool initWithTemporaryStorage(ExclusiveContext *cx, InternalBindingsHandle self,
unsigned numArgs, unsigned numVars,
Binding *bindingArray);
@ -201,7 +201,7 @@ class Bindings
Shape *callObjShape() const { return callObjShape_; }
/* Convenience method to get the var index of 'arguments'. */
static unsigned argumentsVarIndex(JSContext *cx, InternalBindingsHandle);
static unsigned argumentsVarIndex(ExclusiveContext *cx, InternalBindingsHandle);
/* Return whether the binding at bindingIndex is aliased. */
bool bindingIsAliased(unsigned bindingIndex);
@ -586,21 +586,26 @@ class JSScript : public js::gc::Cell
//
public:
static JSScript *Create(JSContext *cx, js::HandleObject enclosingScope, bool savedCallerFun,
static JSScript *Create(js::ExclusiveContext *cx,
js::HandleObject enclosingScope, bool savedCallerFun,
const JS::CompileOptions &options, unsigned staticLevel,
JS::HandleScriptSource sourceObject, uint32_t sourceStart,
uint32_t sourceEnd);
void initCompartmentAndPrincipals(js::ExclusiveContext *cx,
const JS::CompileOptions &options);
// Three ways ways to initialize a JSScript. Callers of partiallyInit()
// and fullyInitTrivial() are responsible for notifying the debugger after
// successfully creating any kind (function or other) of new JSScript.
// However, callers of fullyInitFromEmitter() do not need to do this.
static bool partiallyInit(JSContext *cx, JS::Handle<JSScript*> script,
static bool partiallyInit(js::ExclusiveContext *cx, JS::Handle<JSScript*> script,
uint32_t nobjects, uint32_t nregexps,
uint32_t ntrynotes, uint32_t nconsts, uint32_t nTypeSets);
static bool fullyInitTrivial(JSContext *cx, JS::Handle<JSScript*> script); // inits a JSOP_STOP-only script
static bool fullyInitFromEmitter(JSContext *cx, JS::Handle<JSScript*> script,
static bool fullyInitFromEmitter(js::ExclusiveContext *cx, JS::Handle<JSScript*> script,
js::frontend::BytecodeEmitter *bce);
// Initialize a no-op script.
static bool fullyInitTrivial(js::ExclusiveContext *cx, JS::Handle<JSScript*> script);
inline JSPrincipals *principals();
@ -1163,8 +1168,10 @@ class LazyScript : public js::gc::Cell
uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column);
public:
static LazyScript *Create(JSContext *cx, uint32_t numFreeVariables, uint32_t numInnerFunctions,
JSVersion version, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column);
static LazyScript *Create(ExclusiveContext *cx,
uint32_t numFreeVariables, uint32_t numInnerFunctions,
JSVersion version, uint32_t begin, uint32_t end,
uint32_t lineno, uint32_t column);
void initScript(JSScript *script);
JSScript *maybeScript() {
@ -1375,8 +1382,8 @@ struct SharedScriptData
uint32_t length;
jsbytecode data[1];
static SharedScriptData *new_(JSContext *cx, uint32_t codeLength,
uint32_t srcnotesLength, uint32_t natoms);
static SharedScriptData *new_(ExclusiveContext *cx, uint32_t codeLength,
uint32_t srcnotesLength, uint32_t natoms);
HeapPtrAtom *atoms(uint32_t codeLength, uint32_t srcnotesLength) {
uint32_t length = codeLength + srcnotesLength;
@ -1396,7 +1403,7 @@ struct SharedScriptData
* Sets the |code| and |atoms| fields on the given JSScript.
*/
extern bool
SaveSharedScriptData(JSContext *cx, Handle<JSScript *> script, SharedScriptData *ssd);
SaveSharedScriptData(ExclusiveContext *cx, Handle<JSScript *> script, SharedScriptData *ssd);
struct ScriptBytecodeHasher
{

View File

@ -3630,22 +3630,22 @@ js_InitStringClass(JSContext *cx, HandleObject obj)
template <AllowGC allowGC>
JSStableString *
js_NewString(ThreadSafeContext *tcx, jschar *chars, size_t length)
js_NewString(ThreadSafeContext *cx, jschar *chars, size_t length)
{
return JSStableString::new_<allowGC>(tcx, chars, length);
return JSStableString::new_<allowGC>(cx, chars, length);
}
template JSStableString *
js_NewString<CanGC>(ThreadSafeContext *tcx, jschar *chars, size_t length);
js_NewString<CanGC>(ThreadSafeContext *cx, jschar *chars, size_t length);
template JSStableString *
js_NewString<NoGC>(ThreadSafeContext *tcx, jschar *chars, size_t length);
js_NewString<NoGC>(ThreadSafeContext *cx, jschar *chars, size_t length);
JSLinearString *
js_NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t length)
{
if (length == 0)
return cx->runtime()->emptyString;
return cx->emptyString();
JSLinearString *base = baseArg->ensureLinear(cx);
if (!base)
@ -3664,7 +3664,7 @@ js_NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t len
template <AllowGC allowGC>
JSFlatString *
js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n)
js_NewStringCopyN(ExclusiveContext *cx, const jschar *s, size_t n)
{
if (JSShortString::lengthFits(n))
return NewShortString<allowGC>(cx, TwoByteChars(s, n));
@ -3681,36 +3681,36 @@ js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n)
}
template JSFlatString *
js_NewStringCopyN<CanGC>(JSContext *cx, const jschar *s, size_t n);
js_NewStringCopyN<CanGC>(ExclusiveContext *cx, const jschar *s, size_t n);
template JSFlatString *
js_NewStringCopyN<NoGC>(JSContext *cx, const jschar *s, size_t n);
js_NewStringCopyN<NoGC>(ExclusiveContext *cx, const jschar *s, size_t n);
template <AllowGC allowGC>
JSFlatString *
js_NewStringCopyN(ThreadSafeContext *tcx, const char *s, size_t n)
js_NewStringCopyN(ThreadSafeContext *cx, const char *s, size_t n)
{
if (JSShortString::lengthFits(n))
return NewShortString<allowGC>(tcx, JS::Latin1Chars(s, n));
return NewShortString<allowGC>(cx, JS::Latin1Chars(s, n));
jschar *chars = InflateString(tcx, s, &n);
jschar *chars = InflateString(cx, s, &n);
if (!chars)
return NULL;
JSFlatString *str = js_NewString<allowGC>(tcx, chars, n);
JSFlatString *str = js_NewString<allowGC>(cx, chars, n);
if (!str)
js_free(chars);
return str;
}
template JSFlatString *
js_NewStringCopyN<CanGC>(ThreadSafeContext *tcx, const char *s, size_t n);
js_NewStringCopyN<CanGC>(ThreadSafeContext *cx, const char *s, size_t n);
template JSFlatString *
js_NewStringCopyN<NoGC>(ThreadSafeContext *tcx, const char *s, size_t n);
js_NewStringCopyN<NoGC>(ThreadSafeContext *cx, const char *s, size_t n);
template <AllowGC allowGC>
JSFlatString *
js_NewStringCopyZ(JSContext *cx, const jschar *s)
js_NewStringCopyZ(ExclusiveContext *cx, const jschar *s)
{
size_t n = js_strlen(s);
if (JSShortString::lengthFits(n))
@ -3728,23 +3728,23 @@ js_NewStringCopyZ(JSContext *cx, const jschar *s)
}
template JSFlatString *
js_NewStringCopyZ<CanGC>(JSContext *cx, const jschar *s);
js_NewStringCopyZ<CanGC>(ExclusiveContext *cx, const jschar *s);
template JSFlatString *
js_NewStringCopyZ<NoGC>(JSContext *cx, const jschar *s);
js_NewStringCopyZ<NoGC>(ExclusiveContext *cx, const jschar *s);
template <AllowGC allowGC>
JSFlatString *
js_NewStringCopyZ(ThreadSafeContext *tcx, const char *s)
js_NewStringCopyZ(ThreadSafeContext *cx, const char *s)
{
return js_NewStringCopyN<allowGC>(tcx, s, strlen(s));
return js_NewStringCopyN<allowGC>(cx, s, strlen(s));
}
template JSFlatString *
js_NewStringCopyZ<CanGC>(ThreadSafeContext *tcx, const char *s);
js_NewStringCopyZ<CanGC>(ThreadSafeContext *cx, const char *s);
template JSFlatString *
js_NewStringCopyZ<NoGC>(ThreadSafeContext *tcx, const char *s);
js_NewStringCopyZ<NoGC>(ThreadSafeContext *cx, const char *s);
const char *
js_ValueToPrintable(JSContext *cx, const Value &vArg, JSAutoByteString *bytes, bool asSource)
@ -3765,7 +3765,7 @@ js_ValueToPrintable(JSContext *cx, const Value &vArg, JSAutoByteString *bytes, b
template <AllowGC allowGC>
JSString *
js::ToStringSlow(JSContext *cx, typename MaybeRooted<Value, allowGC>::HandleType arg)
js::ToStringSlow(ExclusiveContext *cx, typename MaybeRooted<Value, allowGC>::HandleType arg)
{
/* As with ToObjectSlow, callers must verify that |arg| isn't a string. */
JS_ASSERT(!arg.isString());
@ -3775,7 +3775,7 @@ js::ToStringSlow(JSContext *cx, typename MaybeRooted<Value, allowGC>::HandleType
if (!allowGC)
return NULL;
RootedValue v2(cx, v);
if (!ToPrimitive(cx, JSTYPE_STRING, &v2))
if (!ToPrimitive(cx->asJSContext(), JSTYPE_STRING, &v2))
return NULL;
v = v2;
}
@ -3798,10 +3798,10 @@ js::ToStringSlow(JSContext *cx, typename MaybeRooted<Value, allowGC>::HandleType
}
template JSString *
js::ToStringSlow<CanGC>(JSContext *cx, HandleValue arg);
js::ToStringSlow<CanGC>(ExclusiveContext *cx, HandleValue arg);
template JSString *
js::ToStringSlow<NoGC>(JSContext *cx, Value arg);
js::ToStringSlow<NoGC>(ExclusiveContext *cx, Value arg);
JSString *
js::ValueToSource(JSContext *cx, HandleValue v)
@ -3972,14 +3972,14 @@ js_strchr_limit(const jschar *s, jschar c, const jschar *limit)
}
jschar *
js::InflateString(ThreadSafeContext *tcx, const char *bytes, size_t *lengthp)
js::InflateString(ThreadSafeContext *cx, const char *bytes, size_t *lengthp)
{
size_t nchars;
jschar *chars;
size_t nbytes = *lengthp;
nchars = nbytes;
chars = tcx->pod_malloc<jschar>(nchars + 1);
chars = cx->pod_malloc<jschar>(nchars + 1);
if (!chars)
goto bad;
for (size_t i = 0; i < nchars; i++)

View File

@ -117,7 +117,7 @@ extern const char js_encodeURIComponent_str[];
/* GC-allocate a string descriptor for the given malloc-allocated chars. */
template <js::AllowGC allowGC>
extern JSStableString *
js_NewString(js::ThreadSafeContext *tcx, jschar *chars, size_t length);
js_NewString(js::ThreadSafeContext *cx, jschar *chars, size_t length);
extern JSLinearString *
js_NewDependentString(JSContext *cx, JSString *base, size_t start, size_t length);
@ -125,20 +125,20 @@ js_NewDependentString(JSContext *cx, JSString *base, size_t start, size_t length
/* Copy a counted string and GC-allocate a descriptor for it. */
template <js::AllowGC allowGC>
extern JSFlatString *
js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n);
js_NewStringCopyN(js::ExclusiveContext *cx, const jschar *s, size_t n);
template <js::AllowGC allowGC>
extern JSFlatString *
js_NewStringCopyN(js::ThreadSafeContext *tcx, const char *s, size_t n);
js_NewStringCopyN(js::ThreadSafeContext *cx, const char *s, size_t n);
/* Copy a C string and GC-allocate a descriptor for it. */
template <js::AllowGC allowGC>
extern JSFlatString *
js_NewStringCopyZ(JSContext *cx, const jschar *s);
js_NewStringCopyZ(js::ExclusiveContext *cx, const jschar *s);
template <js::AllowGC allowGC>
extern JSFlatString *
js_NewStringCopyZ(js::ThreadSafeContext *tcx, const char *s);
js_NewStringCopyZ(js::ThreadSafeContext *cx, const char *s);
/*
* Convert a value to a printable C string.
@ -155,7 +155,7 @@ namespace js {
*/
template <AllowGC allowGC>
extern JSString *
ToStringSlow(JSContext *cx, typename MaybeRooted<Value, allowGC>::HandleType arg);
ToStringSlow(ExclusiveContext *cx, typename MaybeRooted<Value, allowGC>::HandleType arg);
/*
* Convert the given value to a string. This method includes an inline
@ -280,7 +280,7 @@ InflateUTF8String(JSContext *cx, const char *bytes, size_t *length);
* return, will contain on return the number of copied chars.
*/
extern bool
InflateStringToBuffer(JSContext *cx, const char *bytes, size_t length,
InflateStringToBuffer(JSContext *maybecx, const char *bytes, size_t length,
jschar *chars, size_t *charsLength);
extern bool

View File

@ -3160,7 +3160,7 @@ Parse(JSContext *cx, unsigned argc, jsval *vp)
CompileOptions options(cx);
options.setFileAndLine("<string>", 1)
.setCompileAndGo(false);
Parser<FullParseHandler> parser(cx, options,
Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options,
JS_GetStringCharsZ(cx, scriptContents),
JS_GetStringLength(scriptContents),
/* foldConstants = */ true, NULL, NULL);
@ -3201,7 +3201,8 @@ SyntaxParse(JSContext *cx, unsigned argc, jsval *vp)
const jschar *chars = JS_GetStringCharsZ(cx, scriptContents);
size_t length = JS_GetStringLength(scriptContents);
Parser<frontend::SyntaxParseHandler> parser(cx, options, chars, length, false, NULL, NULL);
Parser<frontend::SyntaxParseHandler> parser(cx, &cx->tempLifoAlloc(),
options, chars, length, false, NULL, NULL);
bool succeeded = parser.parse(NULL);
if (cx->isExceptionPending())

View File

@ -180,7 +180,7 @@ ArgumentsObject::create(JSContext *cx, HandleScript script, HandleFunction calle
bool strict = callee->strict();
Class *clasp = strict ? &StrictArgumentsObject::class_ : &NormalArgumentsObject::class_;
RootedTypeObject type(cx, proto->getNewType(cx, clasp));
RootedTypeObject type(cx, cx->getNewType(clasp, proto.get()));
if (!type)
return NULL;

View File

@ -233,7 +233,7 @@ FetchName(JSContext *cx, HandleObject obj, HandleObject obj2, HandlePropertyName
return true;
}
JSAutoByteString printable;
if (js_AtomToPrintableString(cx, name, &printable))
if (AtomToPrintableString(cx, name, &printable))
js_ReportIsNotDefined(cx, printable.ptr());
return false;
}
@ -329,7 +329,7 @@ DefVarOrConstOperation(JSContext *cx, HandleObject varobj, HandlePropertyName dn
return false;
if (attrs & JSPROP_READONLY) {
JSAutoByteString bytes;
if (js_AtomToPrintableString(cx, dn, &bytes)) {
if (AtomToPrintableString(cx, dn, &bytes)) {
JS_ALWAYS_FALSE(JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
js_GetErrorMessage,
NULL, JSMSG_REDECLARED_VAR,

View File

@ -3263,7 +3263,7 @@ js::GetScopeName(JSContext *cx, HandleObject scopeChain, HandlePropertyName name
if (!shape) {
JSAutoByteString printable;
if (js_AtomToPrintableString(cx, name, &printable))
if (AtomToPrintableString(cx, name, &printable))
js_ReportIsNotDefined(cx, printable.ptr());
return false;
}
@ -3392,7 +3392,7 @@ js::DefFunOperation(JSContext *cx, HandleScript script, HandleObject scopeChain,
if (shape->isAccessorDescriptor() || !shape->writable() || !shape->enumerable()) {
JSAutoByteString bytes;
if (js_AtomToPrintableString(cx, name, &bytes)) {
if (AtomToPrintableString(cx, name, &bytes)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_REDEFINE_PROP,
bytes.ptr());
}

View File

@ -27,7 +27,7 @@ js::ObjectImpl::compartment() const
}
inline bool
js::ObjectImpl::nativeContains(JSContext *cx, Shape *shape)
js::ObjectImpl::nativeContains(ExclusiveContext *cx, Shape *shape)
{
return nativeLookup(cx, shape->propid()) == shape;
}
@ -48,12 +48,12 @@ js::ObjectImpl::nonProxyIsExtensible() const
}
/* static */ inline bool
js::ObjectImpl::isExtensible(JSContext *cx, js::Handle<ObjectImpl*> obj, bool *extensible)
js::ObjectImpl::isExtensible(ExclusiveContext *cx, js::Handle<ObjectImpl*> obj, bool *extensible)
{
if (obj->isProxy()) {
HandleObject h =
HandleObject::fromMarkedLocation(reinterpret_cast<JSObject* const*>(obj.address()));
return Proxy::isExtensible(cx, h, extensible);
return Proxy::isExtensible(cx->asJSContext(), h, extensible);
}
*extensible = obj->nonProxyIsExtensible();

View File

@ -322,7 +322,7 @@ js::ObjectImpl::slotInRange(uint32_t slot, SentinelAllowed sentinel) const
MOZ_NEVER_INLINE
#endif
Shape *
js::ObjectImpl::nativeLookup(JSContext *cx, jsid id)
js::ObjectImpl::nativeLookup(ExclusiveContext *cx, jsid id)
{
MOZ_ASSERT(isNative());
Shape **spp;

View File

@ -1242,7 +1242,7 @@ class ObjectImpl : public gc::Cell
}
static inline bool
isExtensible(JSContext *cx, Handle<ObjectImpl*> obj, bool *extensible);
isExtensible(ExclusiveContext *cx, Handle<ObjectImpl*> obj, bool *extensible);
// Indicates whether a non-proxy is extensible. Don't call on proxies!
// This method really shouldn't exist -- but there are a few internal
@ -1292,18 +1292,19 @@ class ObjectImpl : public gc::Cell
#endif
Shape *
replaceWithNewEquivalentShape(JSContext *cx, Shape *existingShape, Shape *newShape = NULL);
replaceWithNewEquivalentShape(ExclusiveContext *cx,
Shape *existingShape, Shape *newShape = NULL);
enum GenerateShape {
GENERATE_NONE,
GENERATE_SHAPE
};
bool setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag,
bool setFlag(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag,
GenerateShape generateShape = GENERATE_NONE);
bool clearFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag);
bool clearFlag(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag);
bool toDictionaryMode(JSContext *cx);
bool toDictionaryMode(ExclusiveContext *cx);
private:
/*
@ -1424,7 +1425,7 @@ class ObjectImpl : public gc::Cell
return shape_;
}
bool generateOwnShape(JSContext *cx, js::Shape *newShape = NULL) {
bool generateOwnShape(ExclusiveContext *cx, js::Shape *newShape = NULL) {
return replaceWithNewEquivalentShape(cx, lastProperty(), newShape);
}
@ -1462,21 +1463,21 @@ class ObjectImpl : public gc::Cell
/* Compute dynamicSlotsCount() for this object. */
inline uint32_t numDynamicSlots() const;
Shape *nativeLookup(JSContext *cx, jsid id);
Shape *nativeLookup(JSContext *cx, PropertyId pid) {
Shape *nativeLookup(ExclusiveContext *cx, jsid id);
Shape *nativeLookup(ExclusiveContext *cx, PropertyId pid) {
return nativeLookup(cx, pid.asId());
}
Shape *nativeLookup(JSContext *cx, PropertyName *name) {
Shape *nativeLookup(ExclusiveContext *cx, PropertyName *name) {
return nativeLookup(cx, NameToId(name));
}
bool nativeContains(JSContext *cx, jsid id) {
bool nativeContains(ExclusiveContext *cx, jsid id) {
return nativeLookup(cx, id) != NULL;
}
bool nativeContains(JSContext *cx, PropertyName* name) {
bool nativeContains(ExclusiveContext *cx, PropertyName* name) {
return nativeLookup(cx, name) != NULL;
}
inline bool nativeContains(JSContext *cx, Shape* shape);
inline bool nativeContains(ExclusiveContext *cx, Shape* shape);
/*
* Contextless; can be called from parallel code. Returns false if the

View File

@ -83,7 +83,7 @@ bool stopExecution(JSScript *script);
/*
* Object has been created. |obj| must exist (its class and size are read)
*/
bool createObject(JSContext *cx, JSObject *obj);
bool createObject(ExclusiveContext *cx, JSObject *obj);
/*
* Object is about to be finalized. |obj| must still exist (its class is
@ -139,7 +139,7 @@ static const char *ObjectClassname(JSObject *obj) {
#endif
inline bool
Probes::createObject(JSContext *cx, JSObject *obj)
Probes::createObject(ExclusiveContext *cx, JSObject *obj)
{
bool ok = true;

View File

@ -31,7 +31,7 @@ RegExpObject::shared(RegExpGuard *g) const
}
inline bool
RegExpObject::getShared(JSContext *cx, RegExpGuard *g)
RegExpObject::getShared(ExclusiveContext *cx, RegExpGuard *g)
{
if (RegExpShared *shared = maybeShared()) {
g->init(*shared);
@ -41,7 +41,7 @@ RegExpObject::getShared(JSContext *cx, RegExpGuard *g)
}
inline void
RegExpObject::setShared(JSContext *cx, RegExpShared &shared)
RegExpObject::setShared(ExclusiveContext *cx, RegExpShared &shared)
{
shared.prepareForUse(cx);
JSObject::setPrivate(&shared);
@ -113,17 +113,17 @@ RegExpToShared(JSContext *cx, HandleObject obj, RegExpGuard *g)
}
inline void
RegExpShared::prepareForUse(JSContext *cx)
RegExpShared::prepareForUse(ExclusiveContext *cx)
{
gcNumberWhenUsed = cx->runtime()->gcNumber;
gcNumberWhenUsed = cx->gcNumber();
}
RegExpGuard::RegExpGuard(JSContext *cx)
RegExpGuard::RegExpGuard(ExclusiveContext *cx)
: re_(NULL), source_(cx)
{
}
RegExpGuard::RegExpGuard(JSContext *cx, RegExpShared &re)
RegExpGuard::RegExpGuard(ExclusiveContext *cx, RegExpShared &re)
: re_(&re), source_(cx, re.source)
{
re_->incRef();

View File

@ -29,7 +29,7 @@ JS_STATIC_ASSERT(StickyFlag == JSREG_STICKY);
/* RegExpObjectBuilder */
RegExpObjectBuilder::RegExpObjectBuilder(JSContext *cx, RegExpObject *reobj)
RegExpObjectBuilder::RegExpObjectBuilder(ExclusiveContext *cx, RegExpObject *reobj)
: cx(cx), reobj_(cx, reobj)
{}
@ -232,7 +232,7 @@ Class RegExpObject::class_ = {
};
RegExpObject *
RegExpObject::create(JSContext *cx, RegExpStatics *res, const jschar *chars, size_t length,
RegExpObject::create(ExclusiveContext *cx, RegExpStatics *res, const jschar *chars, size_t length,
RegExpFlag flags, TokenStream *tokenStream)
{
RegExpFlag staticsFlags = res->getFlags();
@ -240,7 +240,7 @@ RegExpObject::create(JSContext *cx, RegExpStatics *res, const jschar *chars, siz
}
RegExpObject *
RegExpObject::createNoStatics(JSContext *cx, const jschar *chars, size_t length, RegExpFlag flags,
RegExpObject::createNoStatics(ExclusiveContext *cx, const jschar *chars, size_t length, RegExpFlag flags,
TokenStream *tokenStream)
{
RootedAtom source(cx, AtomizeChars<CanGC>(cx, chars, length));
@ -251,7 +251,7 @@ RegExpObject::createNoStatics(JSContext *cx, const jschar *chars, size_t length,
}
RegExpObject *
RegExpObject::createNoStatics(JSContext *cx, HandleAtom source, RegExpFlag flags,
RegExpObject::createNoStatics(ExclusiveContext *cx, HandleAtom source, RegExpFlag flags,
TokenStream *tokenStream)
{
if (!RegExpShared::checkSyntax(cx, tokenStream, source))
@ -262,12 +262,12 @@ RegExpObject::createNoStatics(JSContext *cx, HandleAtom source, RegExpFlag flags
}
bool
RegExpObject::createShared(JSContext *cx, RegExpGuard *g)
RegExpObject::createShared(ExclusiveContext *cx, RegExpGuard *g)
{
Rooted<RegExpObject*> self(cx, this);
JS_ASSERT(!maybeShared());
if (!cx->compartment()->regExps.get(cx, getSource(), getFlags(), g))
if (!cx->regExps().get(cx, getSource(), getFlags(), g))
return false;
self->setShared(cx, **g);
@ -275,7 +275,7 @@ RegExpObject::createShared(JSContext *cx, RegExpGuard *g)
}
Shape *
RegExpObject::assignInitialShape(JSContext *cx)
RegExpObject::assignInitialShape(ExclusiveContext *cx)
{
JS_ASSERT(is<RegExpObject>());
JS_ASSERT(nativeEmpty());
@ -307,7 +307,7 @@ RegExpObject::assignInitialShape(JSContext *cx)
}
bool
RegExpObject::init(JSContext *cx, HandleAtom source, RegExpFlag flags)
RegExpObject::init(ExclusiveContext *cx, HandleAtom source, RegExpFlag flags)
{
Rooted<RegExpObject *> self(cx, this);
@ -382,12 +382,12 @@ RegExpObject::toString(JSContext *cx) const
/* RegExpShared */
RegExpShared::RegExpShared(JSRuntime *rt, JSAtom *source, RegExpFlag flags)
RegExpShared::RegExpShared(JSAtom *source, RegExpFlag flags, uint64_t gcNumber)
: source(source), flags(flags), parenCount(0),
#if ENABLE_YARR_JIT
codeBlock(),
#endif
bytecode(NULL), activeUseCount(0), gcNumberWhenUsed(rt->gcNumber)
bytecode(NULL), activeUseCount(0), gcNumberWhenUsed(gcNumber)
{}
RegExpShared::~RegExpShared()
@ -400,7 +400,7 @@ RegExpShared::~RegExpShared()
}
void
RegExpShared::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
RegExpShared::reportYarrError(ExclusiveContext *cx, TokenStream *ts, ErrorCode error)
{
switch (error) {
case JSC::Yarr::NoError:
@ -410,7 +410,8 @@ RegExpShared::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
if (ts) \
ts->reportError(__msg); \
else \
JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, __msg); \
JS_ReportErrorFlagsAndNumberUC(cx->asJSContext(), \
JSREPORT_ERROR, js_GetErrorMessage, NULL, __msg); \
return
COMPILE_EMSG(PatternTooLarge, JSMSG_REGEXP_TOO_COMPLEX);
COMPILE_EMSG(QuantifierOutOfOrder, JSMSG_BAD_QUANTIFIER);
@ -430,7 +431,7 @@ RegExpShared::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
}
bool
RegExpShared::checkSyntax(JSContext *cx, TokenStream *tokenStream, JSLinearString *source)
RegExpShared::checkSyntax(ExclusiveContext *cx, TokenStream *tokenStream, JSLinearString *source)
{
ErrorCode error = JSC::Yarr::checkSyntax(*source);
if (error == JSC::Yarr::NoError)
@ -683,7 +684,7 @@ RegExpCompartment::sweep(JSRuntime *rt)
}
bool
RegExpCompartment::get(JSContext *cx, JSAtom *source, RegExpFlag flags, RegExpGuard *g)
RegExpCompartment::get(ExclusiveContext *cx, JSAtom *source, RegExpFlag flags, RegExpGuard *g)
{
Key key(source, flags);
Map::AddPtr p = map_.lookupForAdd(key);
@ -692,7 +693,7 @@ RegExpCompartment::get(JSContext *cx, JSAtom *source, RegExpFlag flags, RegExpGu
return true;
}
ScopedJSDeletePtr<RegExpShared> shared(cx->new_<RegExpShared>(cx->runtime(), source, flags));
ScopedJSDeletePtr<RegExpShared> shared(cx->new_<RegExpShared>(source, flags, cx->gcNumber()));
if (!shared)
return false;

View File

@ -55,14 +55,14 @@ enum RegExpRunStatus
class RegExpObjectBuilder
{
JSContext *cx;
ExclusiveContext *cx;
Rooted<RegExpObject*> reobj_;
bool getOrCreate();
bool getOrCreateClone(RegExpObject *proto);
public:
RegExpObjectBuilder(JSContext *cx, RegExpObject *reobj = NULL);
RegExpObjectBuilder(ExclusiveContext *cx, RegExpObject *reobj = NULL);
RegExpObject *reobj() { return reobj_; }
@ -150,7 +150,7 @@ class RegExpShared
bool compileMatchOnlyIfNecessary(JSContext *cx);
public:
RegExpShared(JSRuntime *rt, JSAtom *source, RegExpFlag flags);
RegExpShared(JSAtom *source, RegExpFlag flags, uint64_t gcNumber);
~RegExpShared();
/* Explicit trace function for use by the RegExpStatics and JITs. */
@ -160,11 +160,11 @@ class RegExpShared
/* Static functions to expose some Yarr logic. */
static inline bool isJITRuntimeEnabled(JSContext *cx);
static void reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error);
static bool checkSyntax(JSContext *cx, TokenStream *tokenStream, JSLinearString *source);
static void reportYarrError(ExclusiveContext *cx, TokenStream *ts, ErrorCode error);
static bool checkSyntax(ExclusiveContext *cx, TokenStream *tokenStream, JSLinearString *source);
/* Called when a RegExpShared is installed into a RegExpObject. */
inline void prepareForUse(JSContext *cx);
inline void prepareForUse(ExclusiveContext *cx);
/* Primary interface: run this regular expression on the given string. */
RegExpRunStatus execute(JSContext *cx, const jschar *chars, size_t length,
@ -219,8 +219,8 @@ class RegExpGuard
void operator=(const RegExpGuard &) MOZ_DELETE;
public:
inline RegExpGuard(JSContext *cx);
inline RegExpGuard(JSContext *cx, RegExpShared &re);
inline RegExpGuard(ExclusiveContext *cx);
inline RegExpGuard(ExclusiveContext *cx, RegExpShared &re);
inline ~RegExpGuard();
public:
@ -275,7 +275,7 @@ class RegExpCompartment
bool init(JSContext *cx);
void sweep(JSRuntime *rt);
bool get(JSContext *cx, JSAtom *source, RegExpFlag flags, RegExpGuard *g);
bool get(ExclusiveContext *cx, JSAtom *source, RegExpFlag flags, RegExpGuard *g);
/* Like 'get', but compile 'maybeOpt' (if non-null). */
bool get(JSContext *cx, HandleAtom source, JSString *maybeOpt, RegExpGuard *g);
@ -303,15 +303,15 @@ class RegExpObject : public JSObject
* execution, as opposed to during something like XDR.
*/
static RegExpObject *
create(JSContext *cx, RegExpStatics *res, const jschar *chars, size_t length,
create(ExclusiveContext *cx, RegExpStatics *res, const jschar *chars, size_t length,
RegExpFlag flags, frontend::TokenStream *ts);
static RegExpObject *
createNoStatics(JSContext *cx, const jschar *chars, size_t length, RegExpFlag flags,
createNoStatics(ExclusiveContext *cx, const jschar *chars, size_t length, RegExpFlag flags,
frontend::TokenStream *ts);
static RegExpObject *
createNoStatics(JSContext *cx, HandleAtom atom, RegExpFlag flags, frontend::TokenStream *ts);
createNoStatics(ExclusiveContext *cx, HandleAtom atom, RegExpFlag flags, frontend::TokenStream *ts);
/* Accessors. */
@ -347,8 +347,8 @@ class RegExpObject : public JSObject
bool sticky() const { return getSlot(STICKY_FLAG_SLOT).toBoolean(); }
inline void shared(RegExpGuard *g) const;
inline bool getShared(JSContext *cx, RegExpGuard *g);
inline void setShared(JSContext *cx, RegExpShared &shared);
inline bool getShared(ExclusiveContext *cx, RegExpGuard *g);
inline void setShared(ExclusiveContext *cx, RegExpShared &shared);
private:
friend class RegExpObjectBuilder;
@ -358,15 +358,15 @@ class RegExpObject : public JSObject
* encoding their initial properties. Return the shape after
* changing this regular expression object's last property to it.
*/
Shape *assignInitialShape(JSContext *cx);
Shape *assignInitialShape(ExclusiveContext *cx);
bool init(JSContext *cx, HandleAtom source, RegExpFlag flags);
bool init(ExclusiveContext *cx, HandleAtom source, RegExpFlag flags);
/*
* Precondition: the syntax for |source| has already been validated.
* Side effect: sets the private field.
*/
bool createShared(JSContext *cx, RegExpGuard *g);
bool createShared(ExclusiveContext *cx, RegExpGuard *g);
RegExpShared *maybeShared() const;
/* Call setShared in preference to setPrivate. */

View File

@ -577,12 +577,12 @@ RegExpStatics::checkInvariants()
#endif /* DEBUG */
}
} /* namespace js */
inline js::RegExpStatics *
JSContext::regExpStatics()
inline RegExpStatics *
ExclusiveContext::regExpStatics()
{
return global()->getRegExpStatics();
}
} /* namespace js */
#endif /* vm_RegExpStatics_inl_h */

View File

@ -44,10 +44,13 @@
struct DtoaState;
extern void
js_ReportOutOfMemory(JSContext *cx);
js_ReportOutOfMemory(js::ThreadSafeContext *cx);
extern void
js_ReportAllocationOverflow(JSContext *cx);
js_ReportAllocationOverflow(js::ThreadSafeContext *cx);
extern void
js_ReportOverRecursed(js::ThreadSafeContext *cx);
namespace js {
@ -1163,9 +1166,6 @@ struct JSRuntime : public JS::shadow::Runtime,
ExtraTracerVector gcBlackRootTracers;
ExtraTracer gcGrayRootTracer;
/* Stack of thread-stack-allocated GC roots. */
js::AutoGCRooter *autoGCRooters;
/*
* The GC can only safely decommit memory when the page size of the
* running process matches the compiled arena size.

View File

@ -30,7 +30,7 @@ typedef Rooted<ArgumentsObject *> RootedArgumentsObject;
/*****************************************************************************/
StaticScopeIter::StaticScopeIter(JSContext *cx, JSObject *objArg)
StaticScopeIter::StaticScopeIter(ExclusiveContext *cx, JSObject *objArg)
: obj(cx, objArg), onNamedLambda(false)
{
JS_ASSERT_IF(obj, obj->is<StaticBlockObject>() || obj->is<JSFunction>());
@ -200,7 +200,7 @@ CallObject::createTemplateObject(JSContext *cx, HandleScript script, gc::Initial
RootedShape shape(cx, script->bindings.callObjShape());
JS_ASSERT(shape->getObjectClass() == &class_);
RootedTypeObject type(cx, cx->compartment()->getNewType(cx, &class_, NULL));
RootedTypeObject type(cx, cx->getNewType(&class_, NULL));
if (!type)
return NULL;
@ -330,7 +330,7 @@ Class DeclEnvObject::class_ = {
DeclEnvObject *
DeclEnvObject::createTemplateObject(JSContext *cx, HandleFunction fun, gc::InitialHeap heap)
{
RootedTypeObject type(cx, cx->compartment()->getNewType(cx, &class_, NULL));
RootedTypeObject type(cx, cx->getNewType(&class_, NULL));
if (!type)
return NULL;
@ -374,7 +374,7 @@ DeclEnvObject::create(JSContext *cx, HandleObject enclosing, HandleFunction call
WithObject *
WithObject::create(JSContext *cx, HandleObject proto, HandleObject enclosing, uint32_t depth)
{
RootedTypeObject type(cx, proto->getNewType(cx, &class_));
RootedTypeObject type(cx, cx->getNewType(&class_, proto.get()));
if (!type)
return NULL;
@ -653,7 +653,7 @@ ClonedBlockObject::create(JSContext *cx, Handle<StaticBlockObject *> block, Abst
assertSameCompartment(cx, frame);
JS_ASSERT(block->getClass() == &BlockObject::class_);
RootedTypeObject type(cx, block->getNewType(cx, &BlockObject::class_));
RootedTypeObject type(cx, cx->getNewType(&BlockObject::class_, block.get()));
if (!type)
return NULL;
@ -705,9 +705,9 @@ ClonedBlockObject::copyUnaliasedValues(AbstractFramePtr frame)
}
StaticBlockObject *
StaticBlockObject::create(JSContext *cx)
StaticBlockObject::create(ExclusiveContext *cx)
{
RootedTypeObject type(cx, cx->compartment()->getNewType(cx, &BlockObject::class_, NULL));
RootedTypeObject type(cx, cx->getNewType(&BlockObject::class_, NULL));
if (!type)
return NULL;
@ -725,7 +725,7 @@ StaticBlockObject::create(JSContext *cx)
}
/* static */ Shape *
StaticBlockObject::addVar(JSContext *cx, Handle<StaticBlockObject*> block, HandleId id,
StaticBlockObject::addVar(ExclusiveContext *cx, Handle<StaticBlockObject*> block, HandleId id,
int index, bool *redeclared)
{
JS_ASSERT(JSID_IS_ATOM(id) || (JSID_IS_INT(id) && JSID_TO_INT(id) == index));

View File

@ -57,7 +57,7 @@ class StaticScopeIter
bool onNamedLambda;
public:
explicit StaticScopeIter(JSContext *cx, JSObject *obj);
explicit StaticScopeIter(ExclusiveContext *cx, JSObject *obj);
bool done() const;
void operator++(int);
@ -345,7 +345,7 @@ class BlockObject : public NestedScopeObject
class StaticBlockObject : public BlockObject
{
public:
static StaticBlockObject *create(JSContext *cx);
static StaticBlockObject *create(ExclusiveContext *cx);
/* See StaticScopeIter comment. */
JSObject *enclosingStaticScope() const {
@ -408,8 +408,8 @@ class StaticBlockObject : public BlockObject
void initPrevBlockChainFromParser(StaticBlockObject *prev);
void resetPrevBlockChainFromParser();
static Shape *addVar(JSContext *cx, Handle<StaticBlockObject*> block, HandleId id,
int index, bool *redeclared);
static Shape *addVar(ExclusiveContext *cx, Handle<StaticBlockObject*> block, HandleId id,
int index, bool *redeclared);
};
class ClonedBlockObject : public BlockObject

View File

@ -662,6 +662,20 @@ JSRuntime::initSelfHosting(JSContext *cx)
if (!JS_DefineFunctions(cx, shg, intrinsic_functions))
return false;
/*
* In self-hosting mode, scripts emit JSOP_CALLINTRINSIC instead of
* JSOP_NAME or JSOP_GNAME to access unbound variables. JSOP_CALLINTRINSIC
* does a name lookup in a special object, whose properties are filled in
* lazily upon first access for a given global.
*
* As that object is inaccessible to client code, the lookups are
* guaranteed to return the original objects, ensuring safe implementation
* of self-hosted builtins.
*
* Additionally, the special syntax _CallFunction(receiver, ...args, fun)
* is supported, for which bytecode is emitted that invokes |fun| with
* |receiver| as the this-object and ...args as the arguments..
*/
CompileOptions options(cx);
options.setFileAndLine("self-hosted", 1);
options.setSelfHostingMode(true);

View File

@ -132,6 +132,18 @@ BaseShape::matchesGetterSetter(PropertyOp rawGetter, StrictPropertyOp rawSetter)
return rawGetter == this->rawGetter && rawSetter == this->rawSetter;
}
inline
StackBaseShape::StackBaseShape(ExclusiveContext *cx, Class *clasp,
JSObject *parent, JSObject *metadata, uint32_t objectFlags)
: flags(objectFlags),
clasp(clasp),
parent(parent),
metadata(metadata),
rawGetter(NULL),
rawSetter(NULL),
compartment(cx->compartment_)
{}
inline
StackBaseShape::StackBaseShape(Shape *shape)
: flags(shape->getObjectFlags()),
@ -531,6 +543,59 @@ GetShapeAttributes(HandleShape shape)
return IsImplicitDenseElement(shape) ? JSPROP_ENUMERATE : shape->attributes();
}
inline
AutoRooterGetterSetter::Inner::Inner(ExclusiveContext *cx, uint8_t attrs,
PropertyOp *pgetter_, StrictPropertyOp *psetter_)
: CustomAutoRooter(cx), attrs(attrs),
pgetter(pgetter_), psetter(psetter_),
getterRoot(cx, pgetter_), setterRoot(cx, psetter_)
{
JS_ASSERT_IF(attrs & JSPROP_GETTER, !IsPoisonedPtr(*pgetter));
JS_ASSERT_IF(attrs & JSPROP_SETTER, !IsPoisonedPtr(*psetter));
}
inline
AutoRooterGetterSetter::AutoRooterGetterSetter(ExclusiveContext *cx, uint8_t attrs,
PropertyOp *pgetter, StrictPropertyOp *psetter
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
{
if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
inner.construct(cx, attrs, pgetter, psetter);
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
inline
StackBaseShape::AutoRooter::AutoRooter(ExclusiveContext *cx, const StackBaseShape *base_
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: CustomAutoRooter(cx), base(base_), skip(cx, base_)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
inline
StackShape::AutoRooter::AutoRooter(ExclusiveContext *cx, const StackShape *shape_
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: CustomAutoRooter(cx), shape(shape_), skip(cx, shape_)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
template <AllowGC allowGC>
inline
Shape::Range<allowGC>::Range(ExclusiveContext *cx, Shape *shape)
: cursor(cx, shape)
{
JS_STATIC_ASSERT(allowGC == CanGC);
}
template <AllowGC allowGC>
inline
Shape::Range<allowGC>::Range(Shape *shape)
: cursor((ExclusiveContext *) NULL, shape)
{
JS_STATIC_ASSERT(allowGC == NoGC);
}
} /* namespace js */
#endif /* vm_Shape_inl_h */

View File

@ -30,7 +30,7 @@ using mozilla::DebugOnly;
using mozilla::PodZero;
bool
ShapeTable::init(JSRuntime *rt, Shape *lastProp)
ShapeTable::init(ExclusiveContext *cx, Shape *lastProp)
{
/*
* Either we're creating a table for a large scope that was populated
@ -47,7 +47,7 @@ ShapeTable::init(JSRuntime *rt, Shape *lastProp)
* Use rt->calloc_ for memory accounting and overpressure handling
* without OOM reporting. See ShapeTable::change.
*/
entries = (Shape **) rt->calloc_(sizeOfEntries(JS_BIT(sizeLog2)));
entries = (Shape **) cx->calloc_(sizeOfEntries(JS_BIT(sizeLog2)));
if (!entries)
return false;
@ -67,7 +67,7 @@ ShapeTable::init(JSRuntime *rt, Shape *lastProp)
}
bool
Shape::makeOwnBaseShape(JSContext *cx)
Shape::makeOwnBaseShape(ExclusiveContext *cx)
{
JS_ASSERT(!base()->isOwned());
assertSameCompartmentDebugOnly(cx, compartment());
@ -105,19 +105,18 @@ Shape::handoffTableTo(Shape *shape)
}
/* static */ bool
Shape::hashify(JSContext *cx, Shape *shape)
Shape::hashify(ExclusiveContext *cx, Shape *shape)
{
JS_ASSERT(!shape->hasTable());
if (!shape->ensureOwnBaseShape(cx))
return false;
JSRuntime *rt = cx->runtime();
ShapeTable *table = rt->new_<ShapeTable>(shape->entryCount());
ShapeTable *table = cx->new_<ShapeTable>(shape->entryCount());
if (!table)
return false;
if (!table->init(rt, shape)) {
if (!table->init(cx, shape)) {
js_free(table);
return false;
}
@ -212,7 +211,7 @@ ShapeTable::search(jsid id, bool adding)
}
bool
ShapeTable::change(int log2Delta, JSContext *cx)
ShapeTable::change(int log2Delta, ExclusiveContext *cx)
{
JS_ASSERT(entries);
@ -250,7 +249,7 @@ ShapeTable::change(int log2Delta, JSContext *cx)
}
bool
ShapeTable::grow(JSContext *cx)
ShapeTable::grow(ExclusiveContext *cx)
{
JS_ASSERT(needsToGrow());
@ -258,14 +257,14 @@ ShapeTable::grow(JSContext *cx)
int delta = removedCount < size >> 2;
if (!change(delta, cx) && entryCount + removedCount == size - 1) {
JS_ReportOutOfMemory(cx);
js_ReportOutOfMemory(cx);
return false;
}
return true;
}
Shape *
Shape::getChildBinding(JSContext *cx, const StackShape &child)
Shape::getChildBinding(ExclusiveContext *cx, const StackShape &child)
{
JS_ASSERT(!inDictionary());
@ -278,7 +277,7 @@ Shape::getChildBinding(JSContext *cx, const StackShape &child)
}
/* static */ Shape *
Shape::replaceLastProperty(JSContext *cx, const StackBaseShape &base,
Shape::replaceLastProperty(ExclusiveContext *cx, const StackBaseShape &base,
TaggedProto proto, HandleShape shape)
{
JS_ASSERT(!shape->inDictionary());
@ -310,7 +309,8 @@ Shape::replaceLastProperty(JSContext *cx, const StackBaseShape &base,
* one of lastProperty() or lastProperty()->parent.
*/
/* static */ Shape *
JSObject::getChildProperty(JSContext *cx, HandleObject obj, HandleShape parent, StackShape &child)
JSObject::getChildProperty(ExclusiveContext *cx,
HandleObject obj, HandleShape parent, StackShape &child)
{
/*
* Shared properties have no slot, but slot_ will reflect that of parent.
@ -360,12 +360,12 @@ JSObject::getChildProperty(JSContext *cx, HandleObject obj, HandleShape parent,
}
bool
js::ObjectImpl::toDictionaryMode(JSContext *cx)
js::ObjectImpl::toDictionaryMode(ExclusiveContext *cx)
{
JS_ASSERT(!inDictionaryMode());
/* We allocate the shapes from cx->compartment(), so make sure it's right. */
JS_ASSERT(compartment() == cx->compartment());
JS_ASSERT(cx->isInsideCurrentCompartment(this));
uint32_t span = slotSpan();
@ -440,7 +440,7 @@ NormalizeGetterAndSetter(JSObject *obj,
}
/* static */ Shape *
JSObject::addProperty(JSContext *cx, HandleObject obj, HandleId id,
JSObject::addProperty(ExclusiveContext *cx, HandleObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, int shortid, bool allowDictionary)
@ -451,7 +451,7 @@ JSObject::addProperty(JSContext *cx, HandleObject obj, HandleId id,
if (!JSObject::isExtensible(cx, obj, &extensible))
return NULL;
if (!extensible) {
obj->reportNotExtensible(cx);
obj->reportNotExtensible(cx->asJSContext());
return NULL;
}
@ -478,7 +478,7 @@ ShouldConvertToDictionary(JSObject *obj)
}
/* static */ Shape *
JSObject::addPropertyInternal(JSContext *cx, HandleObject obj, HandleId id,
JSObject::addPropertyInternal(ExclusiveContext *cx, HandleObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, int shortid, Shape **spp,
@ -567,7 +567,7 @@ JSObject::addPropertyInternal(JSContext *cx, HandleObject obj, HandleId id,
* enforce all restrictions from ECMA-262 v5 8.12.9 [[DefineOwnProperty]].
*/
inline bool
CheckCanChangeAttrs(JSContext *cx, JSObject *obj, Shape *shape, unsigned *attrsp)
CheckCanChangeAttrs(ExclusiveContext *cx, JSObject *obj, Shape *shape, unsigned *attrsp)
{
if (shape->configurable())
return true;
@ -578,7 +578,7 @@ CheckCanChangeAttrs(JSContext *cx, JSObject *obj, Shape *shape, unsigned *attrsp
/* Reject attempts to remove a slot from the permanent data property. */
if (shape->isDataDescriptor() && shape->hasSlot() &&
(*attrsp & (JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED))) {
obj->reportNotConfigurable(cx, shape->propid());
obj->reportNotConfigurable(cx->asJSContext(), shape->propid());
return false;
}
@ -586,7 +586,7 @@ CheckCanChangeAttrs(JSContext *cx, JSObject *obj, Shape *shape, unsigned *attrsp
}
/* static */ Shape *
JSObject::putProperty(JSContext *cx, HandleObject obj, HandleId id,
JSObject::putProperty(ExclusiveContext *cx, HandleObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, int shortid)
@ -618,7 +618,7 @@ JSObject::putProperty(JSContext *cx, HandleObject obj, HandleId id,
if (!JSObject::isExtensible(cx, obj, &extensible))
return NULL;
if (!extensible) {
obj->reportNotExtensible(cx);
obj->reportNotExtensible(cx->asJSContext());
return NULL;
}
@ -740,7 +740,7 @@ JSObject::putProperty(JSContext *cx, HandleObject obj, HandleId id,
if (hadSlot && !shape->hasSlot()) {
if (oldSlot < obj->slotSpan())
obj->freeSlot(oldSlot);
++cx->runtime()->propertyRemovals;
++cx->asJSContext()->runtime()->propertyRemovals;
}
obj->checkShapeConsistency();
@ -749,7 +749,7 @@ JSObject::putProperty(JSContext *cx, HandleObject obj, HandleId id,
}
/* static */ Shape *
JSObject::changeProperty(JSContext *cx, HandleObject obj, HandleShape shape, unsigned attrs,
JSObject::changeProperty(ExclusiveContext *cx, HandleObject obj, HandleShape shape, unsigned attrs,
unsigned mask, PropertyOp getter, StrictPropertyOp setter)
{
JS_ASSERT(obj->nativeContains(cx, shape));
@ -790,7 +790,7 @@ JSObject::changeProperty(JSContext *cx, HandleObject obj, HandleShape shape, uns
}
bool
JSObject::removeProperty(JSContext *cx, jsid id_)
JSObject::removeProperty(ExclusiveContext *cx, jsid id_)
{
RootedId id(cx, id_);
RootedObject self(cx, this);
@ -844,7 +844,7 @@ JSObject::removeProperty(JSContext *cx, jsid id_)
/* If shape has a slot, free its slot number. */
if (shape->hasSlot()) {
self->freeSlot(shape->slot());
++cx->runtime()->propertyRemovals;
++cx->asJSContext()->runtime()->propertyRemovals;
}
/*
@ -943,9 +943,9 @@ JSObject::rollbackProperties(JSContext *cx, uint32_t slotSpan)
}
Shape *
js::ObjectImpl::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *newShape)
ObjectImpl::replaceWithNewEquivalentShape(ExclusiveContext *cx, Shape *oldShape, Shape *newShape)
{
JS_ASSERT(cx->compartment() == oldShape->compartment());
JS_ASSERT(cx->isInsideCurrentCompartment(oldShape));
JS_ASSERT_IF(oldShape != lastProperty(),
inDictionaryMode() &&
nativeLookup(cx, oldShape->propidRef()) == oldShape);
@ -997,7 +997,7 @@ js::ObjectImpl::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Sh
}
bool
JSObject::shadowingShapeChange(JSContext *cx, const Shape &shape)
JSObject::shadowingShapeChange(ExclusiveContext *cx, const Shape &shape)
{
return generateOwnShape(cx);
}
@ -1034,7 +1034,7 @@ JSObject::setParent(JSContext *cx, HandleObject obj, HandleObject parent)
}
/* static */ Shape *
Shape::setObjectParent(JSContext *cx, JSObject *parent, TaggedProto proto, Shape *last)
Shape::setObjectParent(ExclusiveContext *cx, JSObject *parent, TaggedProto proto, Shape *last)
{
if (last->getObjectParent() == parent)
return last;
@ -1121,7 +1121,7 @@ js::ObjectImpl::preventExtensions(JSContext *cx, Handle<ObjectImpl*> obj)
}
bool
js::ObjectImpl::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag_,
js::ObjectImpl::setFlag(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag_,
GenerateShape generateShape)
{
BaseShape::Flag flag = (BaseShape::Flag) flag_;
@ -1154,7 +1154,7 @@ js::ObjectImpl::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag_,
}
bool
js::ObjectImpl::clearFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag)
js::ObjectImpl::clearFlag(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag)
{
JS_ASSERT(inDictionaryMode());
JS_ASSERT(lastProperty()->getObjectFlags() & flag);
@ -1172,7 +1172,7 @@ js::ObjectImpl::clearFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag)
}
/* static */ Shape *
Shape::setObjectFlag(JSContext *cx, BaseShape::Flag flag, TaggedProto proto, Shape *last)
Shape::setObjectFlag(ExclusiveContext *cx, BaseShape::Flag flag, TaggedProto proto, Shape *last)
{
if (last->getObjectFlags() & flag)
return last;
@ -1229,9 +1229,9 @@ StackBaseShape::AutoRooter::trace(JSTracer *trc)
}
/* static */ UnownedBaseShape*
BaseShape::getUnowned(JSContext *cx, const StackBaseShape &base)
BaseShape::getUnowned(ExclusiveContext *cx, const StackBaseShape &base)
{
BaseShapeSet &table = cx->compartment()->baseShapes;
BaseShapeSet &table = cx->baseShapes();
if (!table.initialized() && !table.init())
return NULL;
@ -1320,14 +1320,14 @@ InitialShapeEntry::match(const InitialShapeEntry &key, const Lookup &lookup)
}
/* static */ Shape *
EmptyShape::getInitialShape(JSContext *cx, Class *clasp, TaggedProto proto,
EmptyShape::getInitialShape(ExclusiveContext *cx, Class *clasp, TaggedProto proto,
JSObject *parent, JSObject *metadata,
size_t nfixed, uint32_t objectFlags)
{
JS_ASSERT_IF(proto.isObject(), cx->compartment() == proto.toObject()->compartment());
JS_ASSERT_IF(parent, cx->compartment() == parent->compartment());
JS_ASSERT_IF(proto.isObject(), cx->isInsideCurrentCompartment(proto.toObject()));
JS_ASSERT_IF(parent, cx->isInsideCurrentCompartment(parent));
InitialShapeSet &table = cx->compartment()->initialShapes;
InitialShapeSet &table = cx->initialShapes();
if (!table.initialized() && !table.init())
return NULL;
@ -1344,7 +1344,7 @@ EmptyShape::getInitialShape(JSContext *cx, Class *clasp, TaggedProto proto,
RootedObject parentRoot(cx, parent);
RootedObject metadataRoot(cx, metadata);
StackBaseShape base(cx->compartment(), clasp, parent, metadata, objectFlags);
StackBaseShape base(cx, clasp, parent, metadata, objectFlags);
Rooted<UnownedBaseShape*> nbase(cx, BaseShape::getUnowned(cx, base));
if (!nbase)
return NULL;
@ -1364,7 +1364,7 @@ EmptyShape::getInitialShape(JSContext *cx, Class *clasp, TaggedProto proto,
}
/* static */ Shape *
EmptyShape::getInitialShape(JSContext *cx, Class *clasp, TaggedProto proto,
EmptyShape::getInitialShape(ExclusiveContext *cx, Class *clasp, TaggedProto proto,
JSObject *parent, JSObject *metadata,
AllocKind kind, uint32_t objectFlags)
{
@ -1381,7 +1381,7 @@ NewObjectCache::invalidateEntriesForShape(JSContext *cx, HandleShape shape, Hand
kind = GetBackgroundAllocKind(kind);
Rooted<GlobalObject *> global(cx, &shape->getObjectParent()->global());
Rooted<types::TypeObject *> type(cx, proto->getNewType(cx, clasp));
Rooted<types::TypeObject *> type(cx, cx->getNewType(clasp, proto.get()));
EntryIndex entry;
if (lookupGlobal(clasp, global, kind, &entry))
@ -1393,17 +1393,16 @@ NewObjectCache::invalidateEntriesForShape(JSContext *cx, HandleShape shape, Hand
}
/* static */ void
EmptyShape::insertInitialShape(JSContext *cx, HandleShape shape, HandleObject proto)
EmptyShape::insertInitialShape(ExclusiveContext *cx, HandleShape shape, HandleObject proto)
{
InitialShapeEntry::Lookup lookup(shape->getObjectClass(), TaggedProto(proto),
shape->getObjectParent(), shape->getObjectMetadata(),
shape->numFixedSlots(), shape->getObjectFlags());
InitialShapeSet::Ptr p = cx->compartment()->initialShapes.lookup(lookup);
InitialShapeSet::Ptr p = cx->initialShapes().lookup(lookup);
JS_ASSERT(p);
InitialShapeEntry &entry = const_cast<InitialShapeEntry &>(*p);
JS_ASSERT(entry.shape->isEmptyShape());
/* The new shape had better be rooted at the old one. */
#ifdef DEBUG
@ -1418,12 +1417,17 @@ EmptyShape::insertInitialShape(JSContext *cx, HandleShape shape, HandleObject pr
/*
* This affects the shape that will be produced by the various NewObject
* methods, so clear any cache entry referring to the old shape. This is
* not required for correctness (though it may bust on the above asserts):
* the NewObject must always check for a nativeEmpty() result and generate
* the appropriate properties if found. Clearing the cache entry avoids
* this duplicate regeneration.
* not required for correctness: the NewObject must always check for a
* nativeEmpty() result and generate the appropriate properties if found.
* Clearing the cache entry avoids this duplicate regeneration.
*
* Clearing is not necessary when this context is running off the main
* thread, as it will not use the new object cache for allocations.
*/
cx->runtime()->newObjectCache.invalidateEntriesForShape(cx, shape, proto);
if (cx->isJSContext()) {
JSContext *ncx = cx->asJSContext();
ncx->runtime()->newObjectCache.invalidateEntriesForShape(ncx, shape, proto);
}
}
/*

View File

@ -160,15 +160,15 @@ struct ShapeTable {
* and returns false. This will make any extant pointers into the
* table invalid. Don't call this unless needsToGrow() is true.
*/
bool grow(JSContext *cx);
bool grow(ExclusiveContext *cx);
/*
* NB: init and change are fallible but do not report OOM, so callers can
* cope or ignore. They do however use JSRuntime's calloc_ method in order
* to update the malloc counter on success.
* cope or ignore. They do however use the context's calloc_ method in
* order to update the malloc counter on success.
*/
bool init(JSRuntime *rt, Shape *lastProp);
bool change(int log2Delta, JSContext *cx);
bool init(ExclusiveContext *cx, Shape *lastProp);
bool change(int log2Delta, ExclusiveContext *cx);
Shape **search(jsid id, bool adding);
};
@ -339,7 +339,7 @@ class BaseShape : public js::gc::Cell
JS::Zone *zone() const { return tenuredZone(); }
/* Lookup base shapes from the compartment's baseShapes table. */
static UnownedBaseShape* getUnowned(JSContext *cx, const StackBaseShape &base);
static UnownedBaseShape* getUnowned(ExclusiveContext *cx, const StackBaseShape &base);
/* Get the canonical base shape. */
inline UnownedBaseShape* unowned();
@ -414,17 +414,8 @@ struct StackBaseShape
compartment(base->compartment())
{}
StackBaseShape(JSCompartment *comp, Class *clasp,
JSObject *parent, JSObject *metadata, uint32_t objectFlags)
: flags(objectFlags),
clasp(clasp),
parent(parent),
metadata(metadata),
rawGetter(NULL),
rawSetter(NULL),
compartment(comp)
{}
inline StackBaseShape(ExclusiveContext *cx, Class *clasp,
JSObject *parent, JSObject *metadata, uint32_t objectFlags);
inline StackBaseShape(Shape *shape);
inline void updateGetterSetter(uint8_t attrs,
@ -437,12 +428,8 @@ struct StackBaseShape
class AutoRooter : private JS::CustomAutoRooter
{
public:
explicit AutoRooter(JSContext *cx, const StackBaseShape *base_
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: CustomAutoRooter(cx), base(base_), skip(cx, base_)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
inline AutoRooter(ExclusiveContext *cx, const StackBaseShape *base_
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
private:
virtual void trace(JSTracer *trc);
@ -516,8 +503,8 @@ class Shape : public js::gc::Cell
last, else to obj->shape_ */
};
static inline Shape *search(JSContext *cx, Shape *start, jsid id,
Shape ***pspp, bool adding = false);
static inline Shape *search(ExclusiveContext *cx, Shape *start, jsid id,
Shape ***pspp, bool adding = false);
static inline Shape *searchNoHashify(Shape *start, jsid id);
inline void removeFromDictionary(ObjectImpl *obj);
@ -526,24 +513,24 @@ class Shape : public js::gc::Cell
inline void initDictionaryShape(const StackShape &child, uint32_t nfixed,
HeapPtrShape *dictp);
Shape *getChildBinding(JSContext *cx, const StackShape &child);
Shape *getChildBinding(ExclusiveContext *cx, const StackShape &child);
/* Replace the base shape of the last shape in a non-dictionary lineage with base. */
static Shape *replaceLastProperty(JSContext *cx, const StackBaseShape &base,
TaggedProto proto, HandleShape shape);
static Shape *replaceLastProperty(ExclusiveContext *cx, const StackBaseShape &base,
TaggedProto proto, HandleShape shape);
static bool hashify(JSContext *cx, Shape *shape);
static bool hashify(ExclusiveContext *cx, Shape *shape);
void handoffTableTo(Shape *newShape);
inline void setParent(Shape *p);
bool ensureOwnBaseShape(JSContext *cx) {
bool ensureOwnBaseShape(ExclusiveContext *cx) {
if (base()->isOwned())
return true;
return makeOwnBaseShape(cx);
}
bool makeOwnBaseShape(JSContext *cx);
bool makeOwnBaseShape(ExclusiveContext *cx);
public:
bool hasTable() const { return base()->hasTable(); }
@ -573,13 +560,8 @@ class Shape : public js::gc::Cell
typename MaybeRooted<Shape*, allowGC>::RootType cursor;
public:
Range(JSContext *cx, Shape *shape) : cursor(cx, shape) {
JS_STATIC_ASSERT(allowGC == CanGC);
}
Range(Shape *shape) : cursor(NULL, shape) {
JS_STATIC_ASSERT(allowGC == NoGC);
}
inline Range(ExclusiveContext *cx, Shape *shape);
inline Range(Shape *shape);
bool empty() const {
return !cursor || cursor->isEmptyShape();
@ -600,9 +582,12 @@ class Shape : public js::gc::Cell
JSObject *getObjectParent() const { return base()->parent; }
JSObject *getObjectMetadata() const { return base()->metadata; }
static Shape *setObjectParent(JSContext *cx, JSObject *obj, TaggedProto proto, Shape *last);
static Shape *setObjectMetadata(JSContext *cx, JSObject *metadata, TaggedProto proto, Shape *last);
static Shape *setObjectFlag(JSContext *cx, BaseShape::Flag flag, TaggedProto proto, Shape *last);
static Shape *setObjectParent(ExclusiveContext *cx,
JSObject *obj, TaggedProto proto, Shape *last);
static Shape *setObjectMetadata(JSContext *cx,
JSObject *metadata, TaggedProto proto, Shape *last);
static Shape *setObjectFlag(ExclusiveContext *cx,
BaseShape::Flag flag, TaggedProto proto, Shape *last);
uint32_t getObjectFlags() const { return base()->getObjectFlags(); }
bool hasObjectFlag(BaseShape::Flag flag) const {
@ -845,7 +830,7 @@ class Shape : public js::gc::Cell
inline void markChildren(JSTracer *trc);
inline Shape *search(JSContext *cx, jsid id) {
inline Shape *search(ExclusiveContext *cx, jsid id) {
Shape **_;
return search(cx, this, id, &_);
}
@ -866,15 +851,8 @@ class AutoRooterGetterSetter
class Inner : private JS::CustomAutoRooter
{
public:
Inner(JSContext *cx, uint8_t attrs,
PropertyOp *pgetter_, StrictPropertyOp *psetter_)
: CustomAutoRooter(cx), attrs(attrs),
pgetter(pgetter_), psetter(psetter_),
getterRoot(cx, pgetter_), setterRoot(cx, psetter_)
{
JS_ASSERT_IF(attrs & JSPROP_GETTER, !IsPoisonedPtr(*pgetter));
JS_ASSERT_IF(attrs & JSPROP_SETTER, !IsPoisonedPtr(*psetter));
}
inline Inner(ExclusiveContext *cx, uint8_t attrs,
PropertyOp *pgetter_, StrictPropertyOp *psetter_);
private:
virtual void trace(JSTracer *trc);
@ -886,14 +864,9 @@ class AutoRooterGetterSetter
};
public:
explicit AutoRooterGetterSetter(JSContext *cx, uint8_t attrs,
PropertyOp *pgetter, StrictPropertyOp *psetter
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
inner.construct(cx, attrs, pgetter, psetter);
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
inline AutoRooterGetterSetter(ExclusiveContext *cx, uint8_t attrs,
PropertyOp *pgetter, StrictPropertyOp *psetter
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
private:
mozilla::Maybe<Inner> inner;
@ -908,9 +881,11 @@ struct EmptyShape : public js::Shape
* Lookup an initial shape matching the given parameters, creating an empty
* shape if none was found.
*/
static Shape *getInitialShape(JSContext *cx, Class *clasp, TaggedProto proto, JSObject *metadata,
static Shape *getInitialShape(ExclusiveContext *cx, Class *clasp,
TaggedProto proto, JSObject *metadata,
JSObject *parent, size_t nfixed, uint32_t objectFlags = 0);
static Shape *getInitialShape(JSContext *cx, Class *clasp, TaggedProto proto, JSObject *metadata,
static Shape *getInitialShape(ExclusiveContext *cx, Class *clasp,
TaggedProto proto, JSObject *metadata,
JSObject *parent, gc::AllocKind kind, uint32_t objectFlags = 0);
/*
@ -918,7 +893,7 @@ struct EmptyShape : public js::Shape
* getInitialShape calls, until the new shape becomes unreachable in a GC
* and the table entry is purged.
*/
static void insertInitialShape(JSContext *cx, HandleShape shape, HandleObject proto);
static void insertInitialShape(ExclusiveContext *cx, HandleShape shape, HandleObject proto);
};
/*
@ -1020,12 +995,8 @@ struct StackShape
class AutoRooter : private JS::CustomAutoRooter
{
public:
explicit AutoRooter(JSContext *cx, const StackShape *shape_
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: CustomAutoRooter(cx), shape(shape_), skip(cx, shape_)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
inline AutoRooter(ExclusiveContext *cx, const StackShape *shape_
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
private:
virtual void trace(JSTracer *trc);
@ -1060,7 +1031,7 @@ struct StackShape
namespace js {
inline Shape *
Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
Shape::search(ExclusiveContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
{
if (start->inDictionary()) {
*pspp = start->table().search(id, adding);

View File

@ -20,13 +20,13 @@ namespace js {
template <AllowGC allowGC>
static JS_ALWAYS_INLINE JSInlineString *
NewShortString(ThreadSafeContext *tcx, JS::Latin1Chars chars)
NewShortString(ThreadSafeContext *cx, JS::Latin1Chars chars)
{
size_t len = chars.length();
JS_ASSERT(JSShortString::lengthFits(len));
JSInlineString *str = JSInlineString::lengthFits(len)
? JSInlineString::new_<allowGC>(tcx)
: JSShortString::new_<allowGC>(tcx);
? JSInlineString::new_<allowGC>(cx)
: JSShortString::new_<allowGC>(cx);
if (!str)
return NULL;
@ -39,7 +39,7 @@ NewShortString(ThreadSafeContext *tcx, JS::Latin1Chars chars)
template <AllowGC allowGC>
static JS_ALWAYS_INLINE JSInlineString *
NewShortString(JSContext *cx, JS::StableTwoByteChars chars)
NewShortString(ExclusiveContext *cx, JS::StableTwoByteChars chars)
{
size_t len = chars.length();
@ -62,7 +62,7 @@ NewShortString(JSContext *cx, JS::StableTwoByteChars chars)
template <AllowGC allowGC>
static JS_ALWAYS_INLINE JSInlineString *
NewShortString(JSContext *cx, JS::TwoByteChars chars)
NewShortString(ExclusiveContext *cx, JS::TwoByteChars chars)
{
size_t len = chars.length();
@ -145,10 +145,9 @@ JSString::readBarrier(JSString *str)
}
JS_ALWAYS_INLINE bool
JSString::validateLength(js::ThreadSafeContext *maybetcx, size_t length)
JSString::validateLength(js::ThreadSafeContext *maybecx, size_t length)
{
if (JS_UNLIKELY(length > JSString::MAX_LENGTH)) {
JSContext *maybecx = maybetcx && maybetcx->isJSContext() ? maybetcx->asJSContext() : NULL;
js_ReportAllocationOverflow(maybecx);
return false;
}
@ -168,15 +167,14 @@ JSRope::init(JSString *left, JSString *right, size_t length)
template <js::AllowGC allowGC>
JS_ALWAYS_INLINE JSRope *
JSRope::new_(js::ThreadSafeContext *tcx,
JSRope::new_(js::ThreadSafeContext *cx,
typename js::MaybeRooted<JSString*, allowGC>::HandleType left,
typename js::MaybeRooted<JSString*, allowGC>::HandleType right,
size_t length)
{
js::ThreadSafeContext *tcxIfCanGC = allowGC ? tcx : NULL;
if (!validateLength(tcxIfCanGC, length))
if (!validateLength(cx, length))
return NULL;
JSRope *str = (JSRope *) js_NewGCString<allowGC>(tcx);
JSRope *str = (JSRope *) js_NewGCString<allowGC>(cx);
if (!str)
return NULL;
str->init(left, right, length);
@ -201,7 +199,8 @@ JSDependentString::init(JSLinearString *base, const jschar *chars, size_t length
}
JS_ALWAYS_INLINE JSLinearString *
JSDependentString::new_(JSContext *cx, JSLinearString *baseArg, const jschar *chars, size_t length)
JSDependentString::new_(js::ExclusiveContext *cx,
JSLinearString *baseArg, const jschar *chars, size_t length)
{
/* Try to avoid long chains of dependent strings. */
while (baseArg->isDependent())
@ -284,13 +283,13 @@ JSStableString::init(const jschar *chars, size_t length)
template <js::AllowGC allowGC>
JS_ALWAYS_INLINE JSStableString *
JSStableString::new_(js::ThreadSafeContext *tcx, const jschar *chars, size_t length)
JSStableString::new_(js::ThreadSafeContext *cx, const jschar *chars, size_t length)
{
JS_ASSERT(chars[length] == jschar(0));
if (!validateLength(tcx->isJSContext() ? tcx->asJSContext() : NULL, length))
if (!validateLength(cx, length))
return NULL;
JSStableString *str = (JSStableString *)js_NewGCString<allowGC>(tcx);
JSStableString *str = (JSStableString *)js_NewGCString<allowGC>(cx);
if (!str)
return NULL;
str->init(chars, length);
@ -299,9 +298,9 @@ JSStableString::new_(js::ThreadSafeContext *tcx, const jschar *chars, size_t len
template <js::AllowGC allowGC>
JS_ALWAYS_INLINE JSInlineString *
JSInlineString::new_(js::ThreadSafeContext *tcx)
JSInlineString::new_(js::ThreadSafeContext *cx)
{
return (JSInlineString *)js_NewGCString<allowGC>(tcx);
return (JSInlineString *)js_NewGCString<allowGC>(cx);
}
JS_ALWAYS_INLINE jschar *
@ -322,9 +321,9 @@ JSInlineString::resetLength(size_t length)
template <js::AllowGC allowGC>
JS_ALWAYS_INLINE JSShortString *
JSShortString::new_(js::ThreadSafeContext *tcx)
JSShortString::new_(js::ThreadSafeContext *cx)
{
return js_NewGCShortString<allowGC>(tcx);
return js_NewGCShortString<allowGC>(cx);
}
JS_ALWAYS_INLINE void

View File

@ -326,12 +326,12 @@ JSRope::flatten(ThreadSafeContext *maybetcx)
template <AllowGC allowGC>
JSString *
js::ConcatStrings(ThreadSafeContext *tcx,
js::ConcatStrings(ThreadSafeContext *cx,
typename MaybeRooted<JSString*, allowGC>::HandleType left,
typename MaybeRooted<JSString*, allowGC>::HandleType right)
{
JS_ASSERT_IF(!left->isAtom(), tcx->isInsideCurrentZone(left));
JS_ASSERT_IF(!right->isAtom(), tcx->isInsideCurrentZone(right));
JS_ASSERT_IF(!left->isAtom(), cx->isInsideCurrentZone(left));
JS_ASSERT_IF(!right->isAtom(), cx->isInsideCurrentZone(right));
size_t leftLen = left->length();
if (leftLen == 0)
@ -342,18 +342,17 @@ js::ConcatStrings(ThreadSafeContext *tcx,
return left;
size_t wholeLength = leftLen + rightLen;
ThreadSafeContext *tcxIfCanGC = allowGC ? tcx : NULL;
if (!JSString::validateLength(tcxIfCanGC, wholeLength))
if (!JSString::validateLength(cx, wholeLength))
return NULL;
if (JSShortString::lengthFits(wholeLength)) {
JSShortString *str = js_NewGCShortString<allowGC>(tcx);
JSShortString *str = js_NewGCShortString<allowGC>(cx);
if (!str)
return NULL;
const jschar *leftChars = left->getChars(tcx);
const jschar *leftChars = left->getChars(cx->asJSContext());
if (!leftChars)
return NULL;
const jschar *rightChars = right->getChars(tcx);
const jschar *rightChars = right->getChars(cx->asJSContext());
if (!rightChars)
return NULL;
@ -364,7 +363,7 @@ js::ConcatStrings(ThreadSafeContext *tcx,
return str;
}
return JSRope::new_<allowGC>(tcx, left, right, wholeLength);
return JSRope::new_<allowGC>(cx, left, right, wholeLength);
}
template JSString *

View File

@ -232,7 +232,7 @@ class JSString : public js::gc::Cell
* representable by a JSString. An allocation overflow is reported if false
* is returned.
*/
static inline bool validateLength(js::ThreadSafeContext *maybetcx, size_t length);
static inline bool validateLength(js::ThreadSafeContext *maybecx, size_t length);
static void staticAsserts() {
JS_STATIC_ASSERT(JS_BITS_PER_WORD >= 32);
@ -445,7 +445,7 @@ class JSRope : public JSString
public:
template <js::AllowGC allowGC>
static inline JSRope *new_(js::ThreadSafeContext *tcx,
static inline JSRope *new_(js::ThreadSafeContext *cx,
typename js::MaybeRooted<JSString*, allowGC>::HandleType left,
typename js::MaybeRooted<JSString*, allowGC>::HandleType right,
size_t length);
@ -508,7 +508,7 @@ class JSDependentString : public JSLinearString
JSDependentString &asDependent() const MOZ_DELETE;
public:
static inline JSLinearString *new_(JSContext *cx, JSLinearString *base,
static inline JSLinearString *new_(js::ExclusiveContext *cx, JSLinearString *base,
const jschar *chars, size_t length);
};
@ -565,7 +565,8 @@ class JSStableString : public JSFlatString
public:
template <js::AllowGC allowGC>
static inline JSStableString *new_(js::ThreadSafeContext *cx, const jschar *chars, size_t length);
static inline JSStableString *new_(js::ThreadSafeContext *cx,
const jschar *chars, size_t length);
JS_ALWAYS_INLINE
JS::StableCharPtr chars() const {
@ -662,7 +663,7 @@ class JSInlineString : public JSFlatString
public:
template <js::AllowGC allowGC>
static inline JSInlineString *new_(js::ThreadSafeContext *tcx);
static inline JSInlineString *new_(js::ThreadSafeContext *cx);
inline jschar *init(size_t length);
@ -698,7 +699,7 @@ class JSShortString : public JSInlineString
public:
template <js::AllowGC allowGC>
static inline JSShortString *new_(js::ThreadSafeContext *tcx);
static inline JSShortString *new_(js::ThreadSafeContext *cx);
static const size_t MAX_SHORT_LENGTH = JSString::NUM_INLINE_CHARS +
INLINE_EXTENSION_CHARS

View File

@ -1728,7 +1728,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
if (!obj)
return NULL;
types::TypeObject *type = proto->getNewType(cx, obj->getClass());
types::TypeObject *type = cx->getNewType(obj->getClass(), proto.get());
if (!type)
return NULL;
obj->setType(type);
@ -2778,7 +2778,7 @@ DataViewObject::create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength,
return NULL;
if (proto) {
types::TypeObject *type = proto->getNewType(cx, &class_);
types::TypeObject *type = cx->getNewType(&class_, TaggedProto(proto));
if (!type)
return NULL;
obj->setType(type);