Bug 777776 - Properly barrier JSScript::scriptSource_. r=terrence

This commit is contained in:
Benjamin Peterson 2012-07-28 15:18:33 -07:00
parent fe3328e43d
commit 9cbf495384
5 changed files with 47 additions and 31 deletions

View File

@ -4864,7 +4864,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
.setVersion(parent->getVersion());
Rooted<JSScript*> script(cx, JSScript::Create(cx, enclosingScope, false, options,
parent->staticLevel + 1,
bce->script->source,
bce->script->scriptSource(),
funbox->bufStart, funbox->bufEnd));
if (!script)
return false;

View File

@ -0,0 +1,5 @@
gczeal(9, 2)
for (a = 0; a < 4; ++a) {
b =
evaluate("/x/g");
}

View File

@ -603,7 +603,7 @@ js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lamb
}
}
bool haveSource = fun->isInterpreted();
if (haveSource && !fun->script()->source && !fun->script()->loadSource(cx, &haveSource))
if (haveSource && !fun->script()->scriptSource() && !fun->script()->loadSource(cx, &haveSource))
return NULL;
if (haveSource) {
RootedScript script(cx, fun->script());
@ -617,7 +617,7 @@ js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lamb
// The source data for functions created by calling the Function
// constructor is only the function's body.
bool funCon = script->sourceStart == 0 && script->source->argumentsNotIncluded();
bool funCon = script->sourceStart == 0 && script->scriptSource()->argumentsNotIncluded();
// Functions created with the constructor should not be using the
// expression body extension.

View File

@ -519,9 +519,9 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
? (1 << ParentFilename)
: (1 << OwnFilename);
}
if (script->source) {
if (script->scriptSource()) {
scriptBits |= (1 << HaveSource);
if (!enclosingScript || enclosingScript->source != script->source)
if (!enclosingScript || enclosingScript->scriptSource() != script->scriptSource())
scriptBits |= (1 << OwnSource);
}
if (script->isGenerator)
@ -635,17 +635,19 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
}
if (scriptBits & (1 << HaveSource)) {
ScriptSource *ss = script->scriptSource();
if (scriptBits & (1 << OwnSource)) {
if (!ScriptSource::performXDR<mode>(xdr, &script->source))
if (!ScriptSource::performXDR<mode>(xdr, &ss))
return false;
} else {
JS_ASSERT(enclosingScript);
if (mode == XDR_DECODE)
script->source = enclosingScript->source;
ss = enclosingScript->scriptSource();
}
if (mode == XDR_DECODE)
script->setScriptSource(cx, ss);
} else if (mode == XDR_DECODE) {
script->source = NULL;
JS_ASSERT_IF(enclosingScript, !enclosingScript->source);
script->setScriptSource(cx, NULL);
JS_ASSERT_IF(enclosingScript, !enclosingScript->scriptSource());
}
if (!xdr->codeUint32(&script->sourceStart))
return false;
@ -1071,10 +1073,21 @@ SourceCompressorThread::waitOnCompression(SourceCompressionToken *userTok)
}
#endif /* JS_THREADSAFE */
void
JSScript::setScriptSource(JSContext *cx, ScriptSource *ss)
{
#ifdef JSGC_INCREMENTAL
// During IGC, we need to barrier writing to scriptSource_.
if (ss && cx->runtime->gcIncrementalState != NO_INCREMENTAL && cx->runtime->gcIsFull)
ss->mark();
#endif
scriptSource_ = ss;
}
bool
JSScript::loadSource(JSContext *cx, bool *worked)
{
JS_ASSERT(!source);
JS_ASSERT(!scriptSource_);
*worked = false;
if (!cx->runtime->sourceHook)
return true;
@ -1089,7 +1102,7 @@ JSScript::loadSource(JSContext *cx, bool *worked)
cx->free_(src);
return false;
}
source = ss;
setScriptSource(cx, ss);
ss->attachToRuntime(cx->runtime);
*worked = true;
return true;
@ -1098,8 +1111,8 @@ JSScript::loadSource(JSContext *cx, bool *worked)
JSFixedString *
JSScript::sourceData(JSContext *cx)
{
JS_ASSERT(source);
return source->substring(cx, sourceStart, sourceEnd);
JS_ASSERT(scriptSource_);
return scriptSource_->substring(cx, sourceStart, sourceEnd);
}
JSFixedString *
@ -1199,16 +1212,6 @@ ScriptSource::createFromSource(JSContext *cx, const jschar *src, uint32_t length
ss->ready_ = false;
#endif
#ifdef JSGC_INCREMENTAL
/*
* During the IGC we need to ensure that source is marked whenever it is
* accessed even if the name was already in the table. At this point old
* scripts pointing to the source may no longer be reachable.
*/
if (cx->runtime->gcIncrementalState != NO_INCREMENTAL && cx->runtime->gcIsFull)
ss->marked = true;
#endif
JS_ASSERT_IF(ownSource, !tok);
#ifdef JS_THREADSAFE
@ -1298,6 +1301,7 @@ ScriptSource::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf)
void
ScriptSource::sweep(JSRuntime *rt)
{
JS_ASSERT(rt->gcIsFull);
ScriptSource *next = rt->scriptSources, **prev = &rt->scriptSources;
while (next) {
ScriptSource *cur = next;
@ -1600,7 +1604,7 @@ JSScript::Create(JSContext *cx, HandleObject enclosingScope, bool savedCallerFun
}
script->staticLevel = uint16_t(staticLevel);
script->source = ss;
script->setScriptSource(cx, ss);
script->sourceStart = bufStart;
script->sourceEnd = bufEnd;
@ -2264,7 +2268,7 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
.setVersion(src->getVersion());
JSScript *dst = JSScript::Create(cx, enclosingScope, src->savedCallerFun,
options, src->staticLevel,
src->source, src->sourceStart, src->sourceEnd);
src->scriptSource(), src->sourceStart, src->sourceEnd);
if (!dst) {
Foreground::free_(data);
return NULL;
@ -2597,8 +2601,8 @@ JSScript::markChildren(JSTracer *trc)
if (filename)
MarkScriptFilename(trc->runtime, filename);
if (trc->runtime->gcIsFull && source && source->onRuntime())
source->mark();
if (trc->runtime->gcIsFull && scriptSource_)
scriptSource_->mark();
}
bindings.trace(trc);

View File

@ -437,9 +437,8 @@ struct JSScript : public js::gc::Cell
/* Persistent type information retained across GCs. */
js::types::TypeScript *types;
js::ScriptSource *source; /* source code */
private:
js::ScriptSource *scriptSource_; /* source code */
#ifdef JS_METHODJIT
JITScriptSet *mJITInfo;
#endif
@ -621,6 +620,14 @@ struct JSScript : public js::gc::Cell
bool loadSource(JSContext *cx, bool *worked);
js::ScriptSource *scriptSource() {
return scriptSource_;
}
void setScriptSource(JSContext *cx, js::ScriptSource *ss);
public:
/* Return whether this script was compiled for 'eval' */
bool isForEval() { return isCachedEval || isActiveEval; }
@ -997,7 +1004,7 @@ struct ScriptSource
SourceCompressionToken *tok = NULL,
bool ownSource = false);
void attachToRuntime(JSRuntime *rt);
void mark() { JS_ASSERT(ready_); JS_ASSERT(onRuntime_); marked = true; }
void mark() { marked = true; }
void destroy(JSRuntime *rt);
uint32_t length() const { return length_; }
bool onRuntime() const { return onRuntime_; }