зеркало из https://github.com/mozilla/gecko-dev.git
Backout 399362c3e135 (bug 894669) for bustage
This commit is contained in:
Родитель
d9d143a3d4
Коммит
544b3a179f
|
@ -172,7 +172,6 @@ static bool compileOnly = false;
|
||||||
static bool fuzzingSafe = false;
|
static bool fuzzingSafe = false;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static bool dumpEntrainedVariables = false;
|
|
||||||
static bool OOM_printAllocationCount = false;
|
static bool OOM_printAllocationCount = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -429,12 +428,6 @@ RunFile(JSContext *cx, Handle<JSObject*> obj, const char *filename, FILE *file,
|
||||||
|
|
||||||
RootedScript script(cx);
|
RootedScript script(cx);
|
||||||
script = JS::Compile(cx, obj, options, file);
|
script = JS::Compile(cx, obj, options, file);
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (dumpEntrainedVariables)
|
|
||||||
AnalyzeEntrainedVariables(cx, script);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JS_SetOptions(cx, oldopts);
|
JS_SetOptions(cx, oldopts);
|
||||||
JS_ASSERT_IF(!script, gGotError);
|
JS_ASSERT_IF(!script, gGotError);
|
||||||
if (script && !compileOnly) {
|
if (script && !compileOnly) {
|
||||||
|
@ -5076,11 +5069,6 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
|
||||||
|
|
||||||
#endif /* JS_ION */
|
#endif /* JS_ION */
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (op->getBoolOption("dump-entrained-variables"))
|
|
||||||
dumpEntrainedVariables = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* |scriptArgs| gets bound on the global before any code is run. */
|
/* |scriptArgs| gets bound on the global before any code is run. */
|
||||||
if (!BindScriptArgs(cx, obj, op))
|
if (!BindScriptArgs(cx, obj, op))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
@ -5314,10 +5302,6 @@ main(int argc, char **argv, char **envp)
|
||||||
"to test JIT codegen (no-op on platforms other than x86).")
|
"to test JIT codegen (no-op on platforms other than x86).")
|
||||||
|| !op.addBoolOption('\0', "fuzzing-safe", "Don't expose functions that aren't safe for "
|
|| !op.addBoolOption('\0', "fuzzing-safe", "Don't expose functions that aren't safe for "
|
||||||
"fuzzers to call")
|
"fuzzers to call")
|
||||||
#ifdef DEBUG
|
|
||||||
|| !op.addBoolOption('\0', "dump-entrained-variables", "Print variables which are "
|
|
||||||
"unnecessarily entrained by inner functions")
|
|
||||||
#endif
|
|
||||||
#ifdef JSGC_GENERATIONAL
|
#ifdef JSGC_GENERATIONAL
|
||||||
|| !op.addBoolOption('\0', "no-ggc", "Disable Generational GC")
|
|| !op.addBoolOption('\0', "no-ggc", "Disable Generational GC")
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2192,175 +2192,3 @@ js::GetDebugScopeForFrame(JSContext *cx, AbstractFramePtr frame)
|
||||||
ScopeIter si(frame, cx);
|
ScopeIter si(frame, cx);
|
||||||
return GetDebugScope(cx, si);
|
return GetDebugScope(cx, si);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
|
|
||||||
typedef HashSet<PropertyName *> PropertyNameSet;
|
|
||||||
|
|
||||||
static bool
|
|
||||||
RemoveReferencedNames(JSContext *cx, HandleScript script, PropertyNameSet &remainingNames)
|
|
||||||
{
|
|
||||||
// Remove from remainingNames --- the closure variables in some outer
|
|
||||||
// script --- any free variables in this script. This analysis isn't perfect:
|
|
||||||
//
|
|
||||||
// - It will not account for free variables in an inner script which are
|
|
||||||
// actually accessing some name in an intermediate script between the
|
|
||||||
// inner and outer scripts. This can cause remainingNames to be an
|
|
||||||
// underapproximation.
|
|
||||||
//
|
|
||||||
// - It will not account for new names introduced via eval. This can cause
|
|
||||||
// remainingNames to be an overapproximation. This would be easy to fix
|
|
||||||
// but is nice to have as the eval will probably not access these
|
|
||||||
// these names and putting eval in an inner script is bad news if you
|
|
||||||
// care about entraining variables unnecessarily.
|
|
||||||
|
|
||||||
for (jsbytecode *pc = script->code;
|
|
||||||
pc != script->code + script->length;
|
|
||||||
pc += GetBytecodeLength(pc))
|
|
||||||
{
|
|
||||||
PropertyName *name;
|
|
||||||
|
|
||||||
switch (JSOp(*pc)) {
|
|
||||||
case JSOP_NAME:
|
|
||||||
case JSOP_CALLNAME:
|
|
||||||
case JSOP_SETNAME:
|
|
||||||
name = script->getName(pc);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case JSOP_GETALIASEDVAR:
|
|
||||||
case JSOP_CALLALIASEDVAR:
|
|
||||||
case JSOP_SETALIASEDVAR:
|
|
||||||
name = ScopeCoordinateName(cx, script, pc);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
name = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name)
|
|
||||||
remainingNames.remove(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (script->hasObjects()) {
|
|
||||||
ObjectArray *objects = script->objects();
|
|
||||||
for (size_t i = 0; i < objects->length; i++) {
|
|
||||||
JSObject *obj = objects->vector[i];
|
|
||||||
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted()) {
|
|
||||||
JSFunction *fun = &obj->as<JSFunction>();
|
|
||||||
RootedScript innerScript(cx, fun->getOrCreateScript(cx));
|
|
||||||
if (!innerScript)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!RemoveReferencedNames(cx, innerScript, remainingNames))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
AnalyzeEntrainedVariablesInScript(JSContext *cx, HandleScript script, HandleScript innerScript)
|
|
||||||
{
|
|
||||||
PropertyNameSet remainingNames(cx);
|
|
||||||
if (!remainingNames.init())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (BindingIter bi(script); bi; bi++) {
|
|
||||||
if (bi->aliased()) {
|
|
||||||
PropertyNameSet::AddPtr p = remainingNames.lookupForAdd(bi->name());
|
|
||||||
if (!p && !remainingNames.add(p, bi->name()))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RemoveReferencedNames(cx, innerScript, remainingNames))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!remainingNames.empty()) {
|
|
||||||
Sprinter buf(cx);
|
|
||||||
if (!buf.init())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
buf.printf("Script ");
|
|
||||||
|
|
||||||
if (JSAtom *name = script->function()->displayAtom()) {
|
|
||||||
buf.putString(name);
|
|
||||||
buf.printf(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.printf("(%s:%d) has variables entrained by ", script->filename(), script->lineno);
|
|
||||||
|
|
||||||
if (JSAtom *name = innerScript->function()->displayAtom()) {
|
|
||||||
buf.putString(name);
|
|
||||||
buf.printf(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.printf("(%s:%d) ::", innerScript->filename(), innerScript->lineno);
|
|
||||||
|
|
||||||
for (PropertyNameSet::Range r = remainingNames.all(); !r.empty(); r.popFront()) {
|
|
||||||
buf.printf(" ");
|
|
||||||
buf.putString(r.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s\n", buf.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (innerScript->hasObjects()) {
|
|
||||||
ObjectArray *objects = innerScript->objects();
|
|
||||||
for (size_t i = 0; i < objects->length; i++) {
|
|
||||||
JSObject *obj = objects->vector[i];
|
|
||||||
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted()) {
|
|
||||||
JSFunction *fun = &obj->as<JSFunction>();
|
|
||||||
RootedScript innerInnerScript(cx, fun->nonLazyScript());
|
|
||||||
if (!AnalyzeEntrainedVariablesInScript(cx, script, innerInnerScript))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for local variables in script or any other script inner to it, which are
|
|
||||||
// part of the script's call object and are unnecessarily entrained by their own
|
|
||||||
// inner scripts which do not refer to those variables. An example is:
|
|
||||||
//
|
|
||||||
// function foo() {
|
|
||||||
// var a, b;
|
|
||||||
// function bar() { return a; }
|
|
||||||
// function baz() { return b; }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// |bar| unnecessarily entrains |b|, and |baz| unnecessarily entrains |a|.
|
|
||||||
bool
|
|
||||||
js::AnalyzeEntrainedVariables(JSContext *cx, HandleScript script)
|
|
||||||
{
|
|
||||||
if (!script->hasObjects())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
ObjectArray *objects = script->objects();
|
|
||||||
for (size_t i = 0; i < objects->length; i++) {
|
|
||||||
JSObject *obj = objects->vector[i];
|
|
||||||
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted()) {
|
|
||||||
JSFunction *fun = &obj->as<JSFunction>();
|
|
||||||
RootedScript innerScript(cx, fun->getOrCreateScript(cx));
|
|
||||||
if (!innerScript)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (script->function() && script->function()->isHeavyweight()) {
|
|
||||||
if (!AnalyzeEntrainedVariablesInScript(cx, script, innerScript))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!AnalyzeEntrainedVariables(cx, innerScript))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -747,11 +747,6 @@ StaticBlockObject::enclosingBlock() const
|
||||||
return obj && obj->is<StaticBlockObject>() ? &obj->as<StaticBlockObject>() : NULL;
|
return obj && obj->is<StaticBlockObject>() ? &obj->as<StaticBlockObject>() : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
bool
|
|
||||||
AnalyzeEntrainedVariables(JSContext *cx, HandleScript script);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
#endif /* vm_ScopeObject_h */
|
#endif /* vm_ScopeObject_h */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче