mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 777776 - Properly barrier JSScript::scriptSource_. r=terrence
This commit is contained in:
parent
fe3328e43d
commit
9cbf495384
@ -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;
|
||||
|
5
js/src/jit-test/tests/basic/bug777776.js
Normal file
5
js/src/jit-test/tests/basic/bug777776.js
Normal file
@ -0,0 +1,5 @@
|
||||
gczeal(9, 2)
|
||||
for (a = 0; a < 4; ++a) {
|
||||
b =
|
||||
evaluate("/x/g");
|
||||
}
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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_; }
|
||||
|
Loading…
Reference in New Issue
Block a user