Bug 969786: Record the introduction script in ScriptSourceObjects. r=sfink

This commit is contained in:
Jim Blandy 2014-02-26 15:20:00 -08:00
parent 5b59ee81f5
commit d7f4619dde
4 changed files with 49 additions and 4 deletions

View File

@ -1269,6 +1269,31 @@ ScriptSourceObject::elementAttributeName() const
return prop; return prop;
} }
void
ScriptSourceObject::initIntroductionScript(JSScript *script)
{
JS_ASSERT(!getReservedSlot(INTRODUCTION_SCRIPT_SLOT).toPrivate());
// There is no equivalent of cross-compartment wrappers for scripts. If
// the introduction script would be in a different compartment from the
// compiled code, we would be creating a cross-compartment script
// reference, which would be bogus. In that case, just don't bother to
// retain the introduction script.
if (script && script->compartment() == compartment())
setReservedSlot(INTRODUCTION_SCRIPT_SLOT, PrivateValue(script));
}
void
ScriptSourceObject::trace(JSTracer *trc, JSObject *obj)
{
ScriptSourceObject *sso = static_cast<ScriptSourceObject *>(obj);
if (JSScript *script = sso->introductionScript()) {
MarkScriptUnbarriered(trc, &script, "ScriptSourceObject introductionScript");
sso->setReservedSlot(INTRODUCTION_SCRIPT_SLOT, PrivateValue(script));
}
}
void void
ScriptSourceObject::finalize(FreeOp *fop, JSObject *obj) ScriptSourceObject::finalize(FreeOp *fop, JSObject *obj)
{ {
@ -1287,7 +1312,11 @@ const Class ScriptSourceObject::class_ = {
JS_EnumerateStub, JS_EnumerateStub,
JS_ResolveStub, JS_ResolveStub,
JS_ConvertStub, JS_ConvertStub,
ScriptSourceObject::finalize finalize,
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
trace
}; };
ScriptSourceObject * ScriptSourceObject *
@ -1307,6 +1336,9 @@ ScriptSourceObject::create(ExclusiveContext *cx, ScriptSource *source,
else else
sourceObject->initSlot(ELEMENT_PROPERTY_SLOT, UndefinedValue()); sourceObject->initSlot(ELEMENT_PROPERTY_SLOT, UndefinedValue());
sourceObject->initSlot(INTRODUCTION_SCRIPT_SLOT, PrivateValue(nullptr));
sourceObject->initIntroductionScript(options.introductionScript());
return sourceObject; return sourceObject;
} }

View File

@ -557,6 +557,7 @@ class ScriptSourceObject : public JSObject
public: public:
static const Class class_; static const Class class_;
static void trace(JSTracer *trc, JSObject *obj);
static void finalize(FreeOp *fop, JSObject *obj); static void finalize(FreeOp *fop, JSObject *obj);
static ScriptSourceObject *create(ExclusiveContext *cx, ScriptSource *source, static ScriptSourceObject *create(ExclusiveContext *cx, ScriptSource *source,
const ReadOnlyCompileOptions &options); const ReadOnlyCompileOptions &options);
@ -571,11 +572,18 @@ class ScriptSourceObject : public JSObject
void initElement(HandleObject element); void initElement(HandleObject element);
const Value &elementAttributeName() const; const Value &elementAttributeName() const;
JSScript *introductionScript() const {
void *untyped = getReservedSlot(INTRODUCTION_SCRIPT_SLOT).toPrivate();
return static_cast<JSScript *>(untyped);
}
void initIntroductionScript(JSScript *script);
private: private:
static const uint32_t SOURCE_SLOT = 0; static const uint32_t SOURCE_SLOT = 0;
static const uint32_t ELEMENT_SLOT = 1; static const uint32_t ELEMENT_SLOT = 1;
static const uint32_t ELEMENT_PROPERTY_SLOT = 2; static const uint32_t ELEMENT_PROPERTY_SLOT = 2;
static const uint32_t RESERVED_SLOTS = 3; static const uint32_t INTRODUCTION_SCRIPT_SLOT = 3;
static const uint32_t RESERVED_SLOTS = 4;
}; };
enum GeneratorKind { NotGenerator, LegacyGenerator, StarGenerator }; enum GeneratorKind { NotGenerator, LegacyGenerator, StarGenerator };

View File

@ -177,8 +177,9 @@ ParseTask::ParseTask(ExclusiveContext *cx, JSObject *exclusiveContextGlobal, JSC
JS::OffThreadCompileCallback callback, void *callbackData) JS::OffThreadCompileCallback callback, void *callbackData)
: cx(cx), options(initCx), chars(chars), length(length), : cx(cx), options(initCx), chars(chars), length(length),
alloc(JSRuntime::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), scopeChain(initCx, scopeChain), alloc(JSRuntime::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), scopeChain(initCx, scopeChain),
exclusiveContextGlobal(initCx, exclusiveContextGlobal), optionsElement(initCx), callback(callback), exclusiveContextGlobal(initCx, exclusiveContextGlobal), optionsElement(initCx),
callbackData(callbackData), script(nullptr), errors(cx), overRecursed(false) optionsIntroductionScript(initCx), callback(callback), callbackData(callbackData),
script(nullptr), errors(cx), overRecursed(false)
{ {
} }
@ -192,6 +193,8 @@ ParseTask::init(JSContext *cx, const ReadOnlyCompileOptions &options)
// point at while it's in the compilation's temporary compartment. // point at while it's in the compilation's temporary compartment.
optionsElement = this->options.element(); optionsElement = this->options.element();
this->options.setElement(nullptr); this->options.setElement(nullptr);
optionsIntroductionScript = this->options.introductionScript();
this->options.setIntroductionScript(nullptr);
return true; return true;
} }
@ -211,6 +214,7 @@ ParseTask::finish()
// was in the temporary compartment. // was in the temporary compartment.
ScriptSourceObject &sso = script->sourceObject()->as<ScriptSourceObject>(); ScriptSourceObject &sso = script->sourceObject()->as<ScriptSourceObject>();
sso.initElement(optionsElement); sso.initElement(optionsElement);
sso.initIntroductionScript(optionsIntroductionScript);
} }
} }

View File

@ -405,6 +405,7 @@ struct ParseTask
// at that point would create cross-compartment references. Instead we // at that point would create cross-compartment references. Instead we
// hold them here, and install them after merging the compartments. // hold them here, and install them after merging the compartments.
PersistentRootedObject optionsElement; PersistentRootedObject optionsElement;
PersistentRootedScript optionsIntroductionScript;
// Callback invoked off the main thread when the parse finishes. // Callback invoked off the main thread when the parse finishes.
JS::OffThreadCompileCallback callback; JS::OffThreadCompileCallback callback;