bug 684529 - remove script object. r=jorendorff

This commit is contained in:
Igor Bukanov 2011-09-22 12:08:55 +02:00
parent 45833dc0a5
commit 328fbe7fcc
24 changed files with 145 additions and 299 deletions

View File

@ -1643,7 +1643,7 @@ nsJSContext::ExecuteScript(void *aScriptObject,
nsCOMPtr<nsIPrincipal> principal;
rv = sSecurityManager->GetObjectPrincipal(mContext,
JS_GetObjectFromScript(script),
JS_GetGlobalFromScript(script),
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -72,7 +72,7 @@ BytecodeCompiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame
bool inDirectivePrologue;
JS_ASSERT(!(tcflags & ~(TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL | TCF_NEED_MUTABLE_SCRIPT |
TCF_COMPILE_FOR_EVAL | TCF_NEED_SCRIPT_OBJECT)));
TCF_COMPILE_FOR_EVAL | TCF_NEED_SCRIPT_GLOBAL)));
/*
* The scripted callerFrame can only be given for compile-and-go scripts

View File

@ -275,7 +275,7 @@ struct StmtInfo {
/*
* The caller is JS_Compile*Script*.
*/
#define TCF_NEED_SCRIPT_OBJECT 0x40000000
#define TCF_NEED_SCRIPT_GLOBAL 0x40000000
/*
* Flags to check for return; vs. return expr; in a function.

View File

@ -1278,30 +1278,33 @@ JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target)
return reinterpret_cast<JSCrossCompartmentCall *>(call);
}
namespace js {
// Declared in jscompartment.h
JSClass js_dummy_class = {
Class dummy_class = {
"jdummy",
JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub,
JS_ConvertStub, NULL,
JSCLASS_NO_OPTIONAL_MEMBERS
JS_ConvertStub
};
} /*namespace js */
JS_PUBLIC_API(JSCrossCompartmentCall *)
JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target)
{
CHECK_REQUEST(cx);
JSObject *scriptObject = target->u.object;
if (!scriptObject) {
JS_ASSERT(!target->isCachedEval);
GlobalObject *global = target->u.globalObject;
if (!global) {
SwitchToCompartment sc(cx, target->compartment());
scriptObject = JS_NewGlobalObject(cx, &js_dummy_class);
if (!scriptObject)
global = GlobalObject::create(cx, &dummy_class);
if (!global)
return NULL;
}
return JS_EnterCrossCompartmentCall(cx, scriptObject);
return JS_EnterCrossCompartmentCall(cx, global);
}
JS_PUBLIC_API(JSCrossCompartmentCall *)
@ -4582,7 +4585,7 @@ CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj, JSPrincipals *p
assertSameCompartment(cx, obj, principals);
AutoLastFrameCheck lfc(cx);
uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_OBJECT;
uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_GLOBAL;
return BytecodeCompiler::compileScript(cx, obj, NULL, principals, tcflags, chars, length,
filename, lineno, version);
}
@ -4759,7 +4762,7 @@ CompileFileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
JS_ASSERT(i <= len);
len = i;
uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_OBJECT;
uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_GLOBAL;
script = BytecodeCompiler::compileScript(cx, obj, NULL, principals, tcflags, buf, len,
filename, 1, cx->findVersion());
cx->free_(buf);
@ -4820,11 +4823,12 @@ JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename, FILE *f
}
JS_PUBLIC_API(JSObject *)
JS_GetObjectFromScript(JSScript *script)
JS_GetGlobalFromScript(JSScript *script)
{
JS_ASSERT(script->u.object);
JS_ASSERT(!script->isCachedEval);
JS_ASSERT(script->u.globalObject);
return script->u.object;
return script->u.globalObject;
}
static JSFunction *
@ -5018,7 +5022,7 @@ EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
uint32 flags = TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_OBJECT;
uint32 flags = TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL;
if (!rval)
flags |= TCF_NO_SCRIPT_RVAL;

View File

@ -3817,7 +3817,7 @@ JS_CompileFileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj,
JSVersion version);
extern JS_PUBLIC_API(JSObject *)
JS_GetObjectFromScript(JSScript *script);
JS_GetGlobalFromScript(JSScript *script);
extern JS_PUBLIC_API(JSFunction *)
JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,

View File

@ -208,8 +208,8 @@ class CompartmentChecker
void check(JSScript *script) {
if (script) {
check(script->compartment());
if (script->u.object)
check(script->u.object);
if (!script->isCachedEval && script->u.globalObject)
check(script->u.globalObject);
}
}

View File

@ -278,7 +278,7 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
if (vp->isObject()) {
JSObject *obj = &vp->toObject();
JS_ASSERT(obj->isCrossCompartmentWrapper());
if (global->getJSClass() != &js_dummy_class && obj->getParent() != global) {
if (global->getClass() != &dummy_class && obj->getParent() != global) {
do {
obj->setParent(global);
obj = obj->getProto();
@ -861,14 +861,11 @@ JSCompartment::getBreakpointSite(jsbytecode *pc)
}
BreakpointSite *
JSCompartment::getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbytecode *pc, JSObject *scriptObject)
JSCompartment::getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbytecode *pc,
GlobalObject *scriptGlobal)
{
JS_ASSERT(script->code <= pc);
JS_ASSERT(pc < script->code + script->length);
JS_ASSERT_IF(scriptObject, scriptObject->isScript() || scriptObject->isFunction());
JS_ASSERT_IF(scriptObject && scriptObject->isFunction(),
scriptObject->getFunctionPrivate()->script() == script);
JS_ASSERT_IF(scriptObject && scriptObject->isScript(), scriptObject->getScript() == script);
BreakpointSiteMap::AddPtr p = breakpointSites.lookupForAdd(pc);
if (!p) {
@ -880,10 +877,10 @@ JSCompartment::getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbyte
}
BreakpointSite *site = p->value;
if (site->scriptObject)
JS_ASSERT_IF(scriptObject, site->scriptObject == scriptObject);
if (site->scriptGlobal)
JS_ASSERT_IF(scriptGlobal, site->scriptGlobal == scriptGlobal);
else
site->scriptObject = scriptObject;
site->scriptGlobal = scriptGlobal;
return site;
}

View File

@ -293,10 +293,11 @@ struct TraceMonitor {
namespace mjit {
class JaegerCompartment;
}
}
/* Defined in jsapi.cpp */
extern JSClass js_dummy_class;
extern Class dummy_class;
} /* namespace js */
#ifndef JS_EVAL_CACHE_SHIFT
# define JS_EVAL_CACHE_SHIFT 6
@ -615,7 +616,7 @@ struct JS_FRIEND_API(JSCompartment) {
js::BreakpointSite *getBreakpointSite(jsbytecode *pc);
js::BreakpointSite *getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbytecode *pc,
JSObject *scriptObject);
js::GlobalObject *scriptGlobal);
void clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSScript *script, JSObject *handler);
void clearTraps(JSContext *cx, JSScript *script);
bool markTrapClosuresIteratively(JSTracer *trc);

View File

@ -1049,9 +1049,6 @@ JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
JSPrincipals *principals;
nbytes = sizeof *script;
if (script->u.object)
nbytes += JS_GetObjectTotalSize(cx, script->u.object);
nbytes += script->length * sizeof script->code[0];
nbytes += script->natoms * sizeof script->atoms[0];
for (size_t i = 0; i < script->natoms; i++)

View File

@ -1558,6 +1558,7 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
uint32 flagsword; /* word for argument count and fun->flags */
cx = xdr->cx;
JSScript *script;
if (xdr->mode == JSXDR_ENCODE) {
fun = (*objp)->getFunctionPrivate();
if (!fun->isInterpreted()) {
@ -1570,12 +1571,14 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
}
firstword = (fun->u.i.skipmin << 2) | !!fun->atom;
flagsword = (fun->nargs << 16) | fun->flags;
script = fun->script();
} else {
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
if (!fun)
return false;
fun->clearParent();
fun->clearType();
script = NULL;
}
AutoObjectRooter tvr(cx, fun);
@ -1587,28 +1590,20 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
if (!JS_XDRUint32(xdr, &flagsword))
return false;
if (!js_XDRScript(xdr, &script))
return false;
if (xdr->mode == JSXDR_DECODE) {
fun->nargs = flagsword >> 16;
JS_ASSERT((flagsword & JSFUN_KINDMASK) >= JSFUN_INTERPRETED);
fun->flags = uint16(flagsword);
fun->u.i.skipmin = uint16(firstword >> 2);
}
/*
* Don't directly store into fun->u.i.script because we want this to happen
* at the same time as we set the script's owner.
*/
JSScript *script = fun->script();
if (!js_XDRScript(xdr, &script))
return false;
if (xdr->mode == JSXDR_DECODE) {
*objp = fun;
fun->setScript(script);
if (!fun->script()->typeSetFunction(cx, fun))
if (!script->typeSetFunction(cx, fun))
return false;
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
js_CallNewScriptHook(cx, fun->script(), fun);
*objp = fun;
}
return true;
@ -1674,10 +1669,8 @@ fun_trace(JSTracer *trc, JSObject *obj)
if (fun->atom)
MarkString(trc, fun->atom, "atom");
if (fun->isInterpreted() && fun->script()) {
CheckScriptOwner(fun->script(), obj);
if (fun->isInterpreted() && fun->script())
MarkScript(trc, fun->script(), "script");
}
}
static void
@ -2421,19 +2414,18 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
JS_ASSERT(script);
JS_ASSERT(script->compartment() == fun->compartment());
JS_ASSERT(script->compartment() != cx->compartment);
JS_OPT_ASSERT(script->ownerObject == fun);
cfun->u.i.script_ = NULL;
JSScript *cscript = js_CloneScript(cx, script);
if (!cscript)
return NULL;
cscript->u.globalObject = cfun->getGlobal();
cfun->setScript(cscript);
if (!cfun->script()->typeSetFunction(cx, cfun))
if (!cscript->typeSetFunction(cx, cfun))
return NULL;
js_CallNewScriptHook(cx, cfun->script(), cfun);
Debugger::onNewScript(cx, cfun->script(), cfun, NULL);
Debugger::onNewScript(cx, cfun->script(), NULL);
}
}
return clone;

View File

@ -203,10 +203,9 @@ struct JSFunction : public JSObject_Slots2
void setScript(JSScript *script) {
JS_ASSERT(isInterpreted());
u.i.script_ = script;
script->setOwnerObject(this);
}
JSScript * maybeScript() const {
JSScript *maybeScript() const {
return isInterpreted() ? script() : NULL;
}

View File

@ -832,8 +832,8 @@ MarkChildren(JSTracer *trc, JSScript *script)
MarkValueRange(trc, constarray->length, constarray->vector, "consts");
}
if (!script->isCachedEval && script->u.object)
MarkObject(trc, *script->u.object, "object");
if (!script->isCachedEval && script->u.globalObject)
MarkObject(trc, *script->u.globalObject, "object");
if (IS_GC_MARKING_TRACER(trc) && script->filename)
js_MarkScriptFilename(script->filename);

View File

@ -1126,7 +1126,6 @@ class EvalScriptGuard
void setNewScript(JSScript *script) {
/* NewScriptFromCG has already called js_CallNewScriptHook. */
JS_ASSERT(!script_ && script);
script->setOwnerObject(JS_CACHED_SCRIPT);
script_ = script;
script_->isActiveEval = true;
}
@ -6751,25 +6750,21 @@ js_GetClassPrototype(JSContext *cx, JSObject *scopeobj, JSProtoKey protoKey,
JS_ASSERT(protoKey < JSProto_LIMIT);
if (protoKey != JSProto_Null) {
if (!scopeobj) {
if (cx->hasfp())
scopeobj = &cx->fp()->scopeChain();
if (!scopeobj) {
scopeobj = cx->globalObject;
if (!scopeobj) {
*protop = NULL;
return true;
}
}
}
scopeobj = scopeobj->getGlobal();
if (scopeobj->isGlobal()) {
const Value &v = scopeobj->getReservedSlot(JSProto_LIMIT + protoKey);
if (v.isObject()) {
*protop = &v.toObject();
GlobalObject *global;
if (scopeobj) {
global = scopeobj->getGlobal();
} else {
global = GetCurrentGlobal(cx);
if (!global) {
*protop = NULL;
return true;
}
}
const Value &v = global->getReservedSlot(JSProto_LIMIT + protoKey);
if (v.isObject()) {
*protop = &v.toObject();
return true;
}
}
return FindClassPrototype(cx, scopeobj, protoKey, protop, clasp);

View File

@ -1184,12 +1184,6 @@ struct JSObject : js::gc::Cell {
inline js::NativeIterator *getNativeIterator() const;
inline void setNativeIterator(js::NativeIterator *);
/*
* Script-related getters.
*/
inline JSScript *getScript() const;
/*
* XML-related getters and setters.
*/
@ -1465,7 +1459,6 @@ struct JSObject : js::gc::Cell {
inline bool isCall() const { return clasp == &js::CallClass; }
inline bool isDeclEnv() const { return clasp == &js::DeclEnvClass; }
inline bool isRegExp() const { return clasp == &js::RegExpClass; }
inline bool isScript() const { return clasp == &js::ScriptClass; }
inline bool isGenerator() const { return clasp == &js::GeneratorClass; }
inline bool isIterator() const { return clasp == &js::IteratorClass; }
inline bool isStopIteration() const { return clasp == &js::StopIterationClass; }

View File

@ -1472,6 +1472,13 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, JSObject *p
return NewNativeClassInstance(cx, clasp, proto, parent, kind);
}
inline GlobalObject *
GetCurrentGlobal(JSContext *cx)
{
JSObject *scopeChain = (cx->hasfp()) ? &cx->fp()->scopeChain() : cx->globalObject;
return scopeChain ? scopeChain->getGlobal() : NULL;
}
bool
FindClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey, JSObject **protop,
Class *clasp);

View File

@ -306,14 +306,6 @@ CheckScript(JSScript *script, JSScript *prev)
}
}
void
CheckScriptOwner(JSScript *script, JSObject *owner)
{
JS_OPT_ASSERT(script->ownerObject == owner);
if (owner != JS_NEW_SCRIPT && owner != JS_CACHED_SCRIPT)
JS_OPT_ASSERT(script->compartment() == owner->compartment());
}
#endif /* JS_CRASH_DIAGNOSTICS */
} /* namespace js */
@ -756,37 +748,6 @@ JSPCCounters::destroy(JSContext *cx)
}
}
static void
script_trace(JSTracer *trc, JSObject *obj)
{
JSScript *script = (JSScript *) obj->getPrivate();
if (script) {
CheckScriptOwner(script, obj);
MarkScript(trc, script, "script");
}
}
JS_FRIEND_DATA(Class) js::ScriptClass = {
"Script",
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
NULL, /* finalize */
NULL, /* reserved0 */
NULL, /* checkAccess */
NULL, /* call */
NULL, /* construct */
NULL, /* xdrObject */
NULL, /* hasInstance */
script_trace
};
/*
* Shared script filename management.
*/
@ -965,7 +926,6 @@ JSScript::NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natom
PodZero(script);
#ifdef JS_CRASH_DIAGNOSTICS
script->cookie1[0] = script->cookie2[0] = JS_SCRIPT_COOKIE;
script->ownerObject = JS_NEW_SCRIPT;
#endif
#if JS_SCRIPT_INLINE_DATA_LIMIT
if (!data)
@ -1241,23 +1201,26 @@ JSScript::NewScriptFromCG(JSContext *cx, CodeGenerator *cg)
return NULL;
fun->setScript(script);
script->u.globalObject = fun->getParent() ? fun->getParent()->getGlobal() : NULL;
} else {
/*
* Initialize script->object, if necessary, so that the debugger has a
* valid holder object.
*/
if ((cg->flags & TCF_NEED_SCRIPT_OBJECT) && !js_NewScriptObject(cx, script))
return NULL;
if (cg->flags & TCF_NEED_SCRIPT_GLOBAL)
script->u.globalObject = GetCurrentGlobal(cx);
}
/* Tell the debugger about this compiled script. */
js_CallNewScriptHook(cx, script, fun);
if (!cg->parent) {
JSObject *owner = fun ? fun : script->u.object;
GlobalObject *compileAndGoGlobal = NULL;
if (script->compileAndGo)
compileAndGoGlobal = (owner ? owner : cg->scopeChain())->getGlobal();
Debugger::onNewScript(cx, script, owner, compileAndGoGlobal);
if (script->compileAndGo) {
compileAndGoGlobal = script->u.globalObject;
if (!compileAndGoGlobal)
compileAndGoGlobal = cg->scopeChain()->getGlobal();
}
Debugger::onNewScript(cx, script, compileAndGoGlobal);
}
return script;
@ -1288,15 +1251,6 @@ JSScript::dataSize(JSUsableSizeFun usf)
return usable ? usable : dataSize();
}
void
JSScript::setOwnerObject(JSObject *owner)
{
#ifdef JS_CRASH_DIAGNOSTICS
CheckScriptOwner(this, JS_NEW_SCRIPT);
ownerObject = owner;
#endif
}
/*
* Nb: srcnotes are variable-length. This function computes the number of
* srcnote *slots*, which may be greater than the number of srcnotes.
@ -1371,27 +1325,6 @@ JSScript::finalize(JSContext *cx)
}
}
JSObject *
js_NewScriptObject(JSContext *cx, JSScript *script)
{
JS_ASSERT(!script->u.object);
JSObject *obj = NewNonFunction<WithProto::Class>(cx, &ScriptClass, NULL, NULL);
if (!obj)
return NULL;
obj->setPrivate(script);
script->u.object = obj;
script->setOwnerObject(obj);
/*
* Clear the object's type/proto, to avoid entraining stuff. Once we no longer use the parent
* for security checks, then we can clear the parent, too.
*/
obj->clearType();
return obj;
}
namespace js {
static const uint32 GSN_CACHE_THRESHOLD = 100;

View File

@ -426,9 +426,6 @@ class JSPCCounters {
static const uint32 JS_SCRIPT_COOKIE = 0xc00cee;
static JSObject * const JS_NEW_SCRIPT = (JSObject *)0x12345678;
static JSObject * const JS_CACHED_SCRIPT = (JSObject *)0x12341234;
struct JSScript : public js::gc::Cell {
/*
* Two successively less primitive ways to make a new JSScript. The first
@ -561,19 +558,20 @@ struct JSScript : public js::gc::Cell {
union {
/*
* A script object of class ScriptClass, to ensure the script is GC'd.
* A global object for the script.
* - All scripts returned by JSAPI functions (JS_CompileScript,
* JS_CompileFile, etc.) have these objects.
* - Function scripts never have script objects; such scripts are owned
* by their function objects.
* JS_CompileFile, etc.) have a non-null globalObject.
* - A function script has a globalObject if the function comes from a
* compile-and-go script.
* - Temporary scripts created by obj_eval, JS_EvaluateScript, and
* similar functions never have these objects; such scripts are
* explicitly destroyed by the code that created them.
* similar functions never have the globalObject field set; for such
* scripts the global should be extracted from the JS frame that
* execute scripts.
*/
JSObject *object;
js::GlobalObject *globalObject;
/* Hash table chaining for JSCompartment::evalCache. */
JSScript *evalHashLink;
JSScript *evalHashLink;
} u;
uint32 *closedSlots; /* vector of closed slots; args first, then vars. */
@ -582,14 +580,10 @@ struct JSScript : public js::gc::Cell {
JSPCCounters pcCounters;
#ifdef JS_CRASH_DIAGNOSTICS
JSObject *ownerObject;
/* All diagnostic fields must be multiples of Cell::CellSize. */
uint32 cookie2[sizeof(JSObject *) == 4 ? 1 : 2];
uint32 cookie2[Cell::CellSize / sizeof(uint32)];
#endif
void setOwnerObject(JSObject *owner);
#ifdef DEBUG
/*
* Unique identifier within the compartment for this script, used for
@ -638,6 +632,11 @@ struct JSScript : public js::gc::Cell {
inline void clearNesting();
/* Return creation time global or null. */
js::GlobalObject *getGlobalObjectOrNull() const {
return isCachedEval ? NULL : u.globalObject;
}
private:
bool makeTypes(JSContext *cx, JSFunction *fun);
bool makeAnalysis(JSContext *cx);
@ -685,7 +684,7 @@ struct JSScript : public js::gc::Cell {
/* Size of the JITScript and all sections. (This method is implemented in MethodJIT.h.) */
JS_FRIEND_API(size_t) jitDataSize(JSUsableSizeFun usf);
#endif
jsbytecode *main() {
@ -803,7 +802,7 @@ struct JSScript : public js::gc::Cell {
* count-style interface.)
*/
bool setStepModeFlag(JSContext *cx, bool step);
/*
* Increment or decrement the single-step count. If the count is non-zero or
* the flag (set by setStepModeFlag) is set, then the script is in
@ -848,9 +847,6 @@ StackDepth(JSScript *script)
JS_END_MACRO
extern JSObject *
js_InitScriptClass(JSContext *cx, JSObject *obj);
extern void
js_MarkScriptFilename(const char *filename);
@ -873,19 +869,11 @@ namespace js {
#ifdef JS_CRASH_DIAGNOSTICS
void
CheckScriptOwner(JSScript *script, JSObject *owner);
void
CheckScript(JSScript *script, JSScript *prev);
#else
inline void
CheckScriptOwner(JSScript *script, JSObject *owner)
{
}
inline void
CheckScript(JSScript *script, JSScript *prev)
{
@ -895,9 +883,6 @@ CheckScript(JSScript *script, JSScript *prev)
} /* namespace js */
extern JSObject *
js_NewScriptObject(JSContext *cx, JSScript *script);
/*
* To perturb as little code as possible, we introduce a js_GetSrcNote lookup
* cache without adding an explicit cx parameter. Thus js_GetSrcNote becomes

View File

@ -215,11 +215,4 @@ JSScript::clearNesting()
}
}
inline JSScript *
JSObject::getScript() const
{
JS_ASSERT(isScript());
return static_cast<JSScript *>(getPrivate());
}
#endif /* jsscriptinlines_h___ */

View File

@ -723,10 +723,9 @@ JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
if (xdr->mode == JSXDR_DECODE) {
JS_ASSERT(!script->compileAndGo);
if (!js_NewScriptObject(xdr->cx, script))
return false;
script->u.globalObject = GetCurrentGlobal(xdr->cx);
js_CallNewScriptHook(xdr->cx, script, NULL);
Debugger::onNewScript(xdr->cx, script, script->u.object, NULL);
Debugger::onNewScript(xdr->cx, script, NULL);
*scriptp = script;
}

View File

@ -1562,9 +1562,7 @@ ValueToScript(JSContext *cx, jsval v, JSFunction **funp = NULL)
JSObject *obj = JSVAL_TO_OBJECT(v);
JSClass *clasp = JS_GET_CLASS(cx, obj);
if (clasp == Jsvalify(&ScriptClass)) {
script = (JSScript *) JS_GetPrivate(cx, obj);
} else if (clasp == Jsvalify(&GeneratorClass)) {
if (clasp == Jsvalify(&GeneratorClass)) {
JSGenerator *gen = (JSGenerator *) JS_GetPrivate(cx, obj);
fun = gen->floatingFrame()->fun();
script = fun->script();
@ -1624,8 +1622,7 @@ GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp,
v = argv[0];
intarg = 0;
if (!JSVAL_IS_PRIMITIVE(v) &&
(JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&FunctionClass) ||
JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&ScriptClass))) {
JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&FunctionClass)) {
script = ValueToScript(cx, v);
if (!script)
return JS_FALSE;

View File

@ -88,7 +88,6 @@ extern Class DebuggerScript_class;
enum {
JSSLOT_DEBUGSCRIPT_OWNER,
JSSLOT_DEBUGSCRIPT_HOLDER, /* PrivateValue, cross-compartment pointer */
JSSLOT_DEBUGSCRIPT_COUNT
};
@ -125,7 +124,7 @@ ReportObjectRequired(JSContext *cx)
/*** Breakpoints *********************************************************************************/
BreakpointSite::BreakpointSite(JSScript *script, jsbytecode *pc)
: script(script), pc(pc), realOpcode(JSOp(*pc)), scriptObject(NULL), enabledCount(0),
: script(script), pc(pc), realOpcode(JSOp(*pc)), scriptGlobal(NULL), enabledCount(0),
trapHandler(NULL), trapClosure(UndefinedValue())
{
JS_ASSERT(realOpcode != JSOP_TRAP);
@ -136,11 +135,11 @@ BreakpointSite::BreakpointSite(JSScript *script, jsbytecode *pc)
* Precondition: script is live, meaning either it is a non-held script that is
* on the stack or a held script that hasn't been GC'd.
*/
static JSObject *
ScriptScope(JSContext *cx, JSScript *script, JSObject *holder)
static GlobalObject *
ScriptGlobal(JSContext *cx, JSScript *script, GlobalObject *scriptGlobal)
{
if (holder)
return holder;
if (scriptGlobal)
return scriptGlobal;
/*
* The referent is a non-held script. There is no direct reference from
@ -149,9 +148,9 @@ ScriptScope(JSContext *cx, JSScript *script, JSObject *holder)
for (AllFramesIter i(cx->stack.space()); ; ++i) {
JS_ASSERT(!i.done());
if (i.fp()->maybeScript() == script)
return &i.fp()->scopeChain();
return i.fp()->scopeChain().getGlobal();
}
JS_NOT_REACHED("ScriptScope: live non-held script not on stack");
JS_NOT_REACHED("ScriptGlobal: live non-held script not on stack");
}
bool
@ -161,7 +160,7 @@ BreakpointSite::recompile(JSContext *cx, bool forTrap)
if (script->hasJITCode()) {
Maybe<AutoCompartment> ac;
if (!forTrap) {
ac.construct(cx, ScriptScope(cx, script, scriptObject));
ac.construct(cx, ScriptGlobal(cx, script, scriptGlobal));
if (!ac.ref().enter())
return false;
}
@ -733,7 +732,7 @@ Debugger::fireEnterFrame(JSContext *cx)
}
void
Debugger::fireNewScript(JSContext *cx, JSScript *script, JSObject *obj)
Debugger::fireNewScript(JSContext *cx, JSScript *script)
{
JSObject *hook = getHook(OnNewScript);
JS_ASSERT(hook);
@ -743,7 +742,7 @@ Debugger::fireNewScript(JSContext *cx, JSScript *script, JSObject *obj)
if (!ac.enter())
return;
JSObject *dsobj = wrapScript(cx, script, obj);
JSObject *dsobj = wrapScript(cx, script);
if (!dsobj) {
handleUncaughtException(ac, NULL, false);
return;
@ -816,8 +815,7 @@ AddNewScriptRecipients(GlobalObject::DebuggerVector *src, AutoValueVector *dest)
}
void
Debugger::slowPathOnNewScript(JSContext *cx, JSScript *script, JSObject *obj,
GlobalObject *compileAndGoGlobal)
Debugger::slowPathOnNewScript(JSContext *cx, JSScript *script, GlobalObject *compileAndGoGlobal)
{
JS_ASSERT(script->compileAndGo == !!compileAndGoGlobal);
@ -849,7 +847,7 @@ Debugger::slowPathOnNewScript(JSContext *cx, JSScript *script, JSObject *obj,
Debugger *dbg = Debugger::fromJSObject(&p->toObject());
if ((!compileAndGoGlobal || dbg->debuggees.has(compileAndGoGlobal)) &&
dbg->enabled && dbg->getHook(OnNewScript)) {
dbg->fireNewScript(cx, script, obj);
dbg->fireNewScript(cx, script);
}
}
}
@ -1782,15 +1780,7 @@ static inline JSScript *
GetScriptReferent(JSObject *obj)
{
JS_ASSERT(obj->getClass() == &DebuggerScript_class);
return (JSScript *) obj->getPrivate();
}
static inline JSObject *
GetScriptHolder(JSObject *obj)
{
JS_ASSERT(obj->getClass() == &DebuggerScript_class);
Value v = obj->getReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER);
return (JSObject *) v.toPrivate();
return static_cast<JSScript *>(obj->getPrivate());
}
static void
@ -1799,11 +1789,6 @@ DebuggerScript_trace(JSTracer *trc, JSObject *obj)
if (!trc->context->runtime->gcCurrentCompartment) {
if (JSScript *script = GetScriptReferent(obj))
MarkScript(trc, script, "Debugger.Script referent");
Value v = obj->getReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER);
if (!v.isUndefined()) {
if (JSObject *obj = (JSObject *) v.toPrivate())
MarkObject(trc, *obj, "Debugger.Script referent holder");
}
}
}
@ -1821,7 +1806,7 @@ Class DebuggerScript_class = {
};
JSObject *
Debugger::newDebuggerScript(JSContext *cx, JSScript *script, JSObject *holder)
Debugger::newDebuggerScript(JSContext *cx, JSScript *script)
{
assertSameCompartment(cx, object);
@ -1832,21 +1817,18 @@ Debugger::newDebuggerScript(JSContext *cx, JSScript *script, JSObject *holder)
return NULL;
scriptobj->setPrivate(script);
scriptobj->setReservedSlot(JSSLOT_DEBUGSCRIPT_OWNER, ObjectValue(*object));
scriptobj->setReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER, PrivateValue(holder));
return scriptobj;
}
JSObject *
Debugger::wrapScript(JSContext *cx, JSScript *script, JSObject *obj)
Debugger::wrapScript(JSContext *cx, JSScript *script)
{
assertSameCompartment(cx, object);
JS_ASSERT(cx->compartment != script->compartment());
JS_ASSERT_IF(obj, script->compartment() == obj->compartment());
CellWeakMap::AddPtr p = scripts.lookupForAdd(script);
if (!p) {
JSObject *scriptobj = newDebuggerScript(cx, script, obj);
JSObject *scriptobj = newDebuggerScript(cx, script);
/* The allocation may have caused a GC, which can remove table entries. */
if (!scriptobj || !scripts.relookupOrAdd(p, script, scriptobj))
@ -1857,12 +1839,6 @@ Debugger::wrapScript(JSContext *cx, JSScript *script, JSObject *obj)
return p->value;
}
JSObject *
Debugger::wrapFunctionScript(JSContext *cx, JSFunction *fun)
{
return wrapScript(cx, fun->script(), fun);
}
static JSObject *
DebuggerScript_check(JSContext *cx, const Value &v, const char *clsname, const char *fnname)
{
@ -1879,15 +1855,14 @@ DebuggerScript_check(JSContext *cx, const Value &v, const char *clsname, const c
/*
* Check for Debugger.Script.prototype, which is of class DebuggerScript_class
* but whose holding object is undefined.
* but whose script is null.
*/
if (thisobj->getReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER).isUndefined()) {
if (!GetScriptReferent(thisobj)) {
JS_ASSERT(!GetScriptReferent(thisobj));
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
clsname, fnname, "prototype object");
return NULL;
}
JS_ASSERT(GetScriptReferent(thisobj));
return thisobj;
}
@ -1954,7 +1929,8 @@ DebuggerScript_getChildScripts(JSContext *cx, uintN argc, Value *vp)
for (uint32 i = script->savedCallerFun ? 1 : 0; i < objects->length; i++) {
JSObject *obj = objects->vector[i];
if (obj->isFunction()) {
JSObject *s = dbg->wrapFunctionScript(cx, (JSFunction *) obj);
JSFunction *fun = static_cast<JSFunction *>(obj);
JSObject *s = dbg->wrapScript(cx, fun->script());
if (!s || !js_NewbornArrayPush(cx, result, ObjectValue(*s)))
return false;
}
@ -2257,8 +2233,8 @@ DebuggerScript_setBreakpoint(JSContext *cx, uintN argc, Value *vp)
THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "setBreakpoint", args, obj, script);
Debugger *dbg = Debugger::fromChildJSObject(obj);
JSObject *holder = GetScriptHolder(obj);
if (!dbg->observesScope(ScriptScope(cx, script, holder))) {
GlobalObject *scriptGlobal = script->getGlobalObjectOrNull();
if (!dbg->observesGlobal(ScriptGlobal(cx, script, scriptGlobal))) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_DEBUGGING);
return false;
}
@ -2273,7 +2249,7 @@ DebuggerScript_setBreakpoint(JSContext *cx, uintN argc, Value *vp)
JSCompartment *comp = script->compartment();
jsbytecode *pc = script->code + offset;
BreakpointSite *site = comp->getOrCreateBreakpointSite(cx, script, pc, holder);
BreakpointSite *site = comp->getOrCreateBreakpointSite(cx, script, pc, scriptGlobal);
if (!site)
return false;
if (site->inc(cx)) {
@ -2628,7 +2604,7 @@ DebuggerFrame_getScript(JSContext *cx, uintN argc, Value *vp)
if (fp->isFunctionFrame() && !fp->isEvalFrame()) {
JSFunction *callee = fp->callee().getFunctionPrivate();
if (callee->isInterpreted()) {
scriptObject = debug->wrapFunctionScript(cx, callee);
scriptObject = debug->wrapScript(cx, callee->script());
if (!scriptObject)
return false;
}
@ -2638,8 +2614,7 @@ DebuggerFrame_getScript(JSContext *cx, uintN argc, Value *vp)
* frames.
*/
JSScript *script = fp->script();
scriptObject = debug->wrapScript(cx, script,
script->isCachedEval ? NULL : script->u.object);
scriptObject = debug->wrapScript(cx, script);
if (!scriptObject)
return false;
}
@ -2744,7 +2719,7 @@ EvaluateInScope(JSContext *cx, JSObject *scobj, StackFrame *fp, const jschar *ch
*/
JSScript *script = BytecodeCompiler::compileScript(cx, scobj, fp,
fp->scopeChain().principals(cx),
TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_OBJECT,
TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL,
chars, length, filename, lineno,
cx->findVersion(), NULL,
UpvarCookie::UPVAR_LEVEL_LIMIT);
@ -3056,7 +3031,7 @@ DebuggerObject_getScript(JSContext *cx, uintN argc, Value *vp)
if (!fun->isInterpreted())
return true;
JSObject *scriptObject = dbg->wrapFunctionScript(cx, fun);
JSObject *scriptObject = dbg->wrapScript(cx, fun->script());
if (!scriptObject)
return false;

View File

@ -201,7 +201,7 @@ class Debugger {
static void slowPathOnEnterFrame(JSContext *cx);
static void slowPathOnLeaveFrame(JSContext *cx);
static void slowPathOnNewScript(JSContext *cx, JSScript *script, JSObject *obj,
static void slowPathOnNewScript(JSContext *cx, JSScript *script,
GlobalObject *compileAndGoGlobal);
static JSTrapStatus dispatchHook(JSContext *cx, js::Value *vp, Hook which);
@ -210,18 +210,16 @@ class Debugger {
void fireEnterFrame(JSContext *cx);
/*
* Allocate and initialize a Debugger.Script instance whose referent is |script| and
* whose holder is |obj|. If |obj| is NULL, this creates a Debugger.Script whose holder
* is null, for non-held scripts.
* Allocate and initialize a Debugger.Script instance whose referent is
* |script|.
*/
JSObject *newDebuggerScript(JSContext *cx, JSScript *script, JSObject *obj);
JSObject *newDebuggerScript(JSContext *cx, JSScript *script);
/*
* Receive a "new script" event from the engine. A new script was compiled
* or deserialized. For eval scripts obj must be null, otherwise it must be
* a script object.
* or deserialized.
*/
void fireNewScript(JSContext *cx, JSScript *script, JSObject *obj);
void fireNewScript(JSContext *cx, JSScript *script);
static inline Debugger *fromLinks(JSCList *links);
inline Breakpoint *firstBreakpoint() const;
@ -262,7 +260,7 @@ class Debugger {
static inline void onLeaveFrame(JSContext *cx);
static inline JSTrapStatus onDebuggerStatement(JSContext *cx, js::Value *vp);
static inline JSTrapStatus onExceptionUnwind(JSContext *cx, js::Value *vp);
static inline void onNewScript(JSContext *cx, JSScript *script, JSObject *obj,
static inline void onNewScript(JSContext *cx, JSScript *script,
GlobalObject *compileAndGoGlobal);
static JSTrapStatus onTrap(JSContext *cx, Value *vp);
static JSTrapStatus onSingleStep(JSContext *cx, Value *vp);
@ -271,7 +269,7 @@ class Debugger {
inline bool observesEnterFrame() const;
inline bool observesNewScript() const;
inline bool observesScope(JSObject *obj) const;
inline bool observesGlobal(GlobalObject *global) const;
inline bool observesFrame(StackFrame *fp) const;
/*
@ -331,21 +329,12 @@ class Debugger {
*/
bool newCompletionValue(AutoCompartment &ac, bool ok, Value val, Value *vp);
/*
* Return the Debugger.Script object for |fun|'s script, or create a new
* one if needed. The context |cx| must be in the debugger compartment;
* |fun| must be a cross-compartment wrapper referring to the JSFunction in
* a debuggee compartment.
*/
JSObject *wrapFunctionScript(JSContext *cx, JSFunction *fun);
/*
* Return the Debugger.Script object for |script|, or create a new one if
* needed. The context |cx| must be in the debugger compartment; |script| must
* be a script in a debuggee compartment. |obj| is either the script holder or
* null for non-held scripts.
* needed. The context |cx| must be in the debugger compartment; |script|
* must be a script in a debuggee compartment.
*/
JSObject *wrapScript(JSContext *cx, JSScript *script, JSObject *obj);
JSObject *wrapScript(JSContext *cx, JSScript *script);
private:
/* Prohibit copying. */
@ -369,7 +358,7 @@ class BreakpointSite {
* cached eval scripts and for JSD1 traps. It is always non-null for JSD2
* breakpoints in held scripts.
*/
JSObject *scriptObject;
GlobalObject *scriptGlobal;
JSCList breakpoints; /* cyclic list of all js::Breakpoints at this instruction */
size_t enabledCount; /* number of breakpoints in the list that are enabled */
@ -383,7 +372,7 @@ class BreakpointSite {
Breakpoint *firstBreakpoint() const;
bool hasBreakpoint(Breakpoint *bp);
bool hasTrap() const { return !!trapHandler; }
JSObject *getScriptObject() const { return scriptObject; }
GlobalObject *getScriptGlobal() const { return scriptGlobal; }
bool inc(JSContext *cx);
void dec(JSContext *cx);
@ -475,15 +464,15 @@ Debugger::observesNewScript() const
}
bool
Debugger::observesScope(JSObject *obj) const
Debugger::observesGlobal(GlobalObject *global) const
{
return debuggees.has(obj->getGlobal());
return debuggees.has(global);
}
bool
Debugger::observesFrame(StackFrame *fp) const
{
return observesScope(&fp->scopeChain());
return observesGlobal(fp->scopeChain().getGlobal());
}
void
@ -517,13 +506,12 @@ Debugger::onExceptionUnwind(JSContext *cx, js::Value *vp)
}
void
Debugger::onNewScript(JSContext *cx, JSScript *script, JSObject *obj,
GlobalObject *compileAndGoGlobal)
Debugger::onNewScript(JSContext *cx, JSScript *script, GlobalObject *compileAndGoGlobal)
{
JS_ASSERT_IF(script->compileAndGo, compileAndGoGlobal);
JS_ASSERT_IF(!script->compileAndGo, !compileAndGoGlobal);
if (!script->compartment()->getDebuggees().empty())
slowPathOnNewScript(cx, script, obj, compileAndGoGlobal);
slowPathOnNewScript(cx, script, compileAndGoGlobal);
}
extern JSBool

View File

@ -373,7 +373,7 @@ js::GlobalObject *
JSObject::asGlobal()
{
JS_ASSERT(isGlobal());
return reinterpret_cast<js::GlobalObject *>(this);
return static_cast<js::GlobalObject *>(this);
}
#endif /* GlobalObject_h___ */

View File

@ -779,15 +779,6 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
if (si) {
JS_snprintf(name, sizeof(name), "JS Object (%s - %s)",
clazz->name, si->GetJSClass()->name);
} else if (clazz == &js::ScriptClass) {
JSScript* script = (JSScript*) xpc_GetJSPrivate(obj);
if (script->filename) {
JS_snprintf(name, sizeof(name),
"JS Object (Script - %s)",
script->filename);
} else {
JS_snprintf(name, sizeof(name), "JS Object (Script)");
}
} else if (clazz == &js::FunctionClass) {
JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj);
JSString* str = JS_GetFunctionId(fun);