Backed out 13 changesets (bug 1165486) for ASAN jsreftest crashes.

Backed out changeset 24966b67d232 (bug 1165486)
Backed out changeset 4a65eeea4d9a (bug 1165486)
Backed out changeset c5301aa7a2ae (bug 1165486)
Backed out changeset fea908d8a836 (bug 1165486)
Backed out changeset ca9561cbcd29 (bug 1165486)
Backed out changeset 91a3217d4cd0 (bug 1165486)
Backed out changeset e74163801eef (bug 1165486)
Backed out changeset ec5df87d2ee5 (bug 1165486)
Backed out changeset 17d21020a786 (bug 1165486)
Backed out changeset 6318eba2d3fe (bug 1165486)
Backed out changeset a103caa36183 (bug 1165486)
Backed out changeset 18c025c16bed (bug 1165486)
Backed out changeset b32fcdc115b6 (bug 1165486)

CLOSED TREE

--HG--
extra : amend_source : 356c5bf7944d6ebb36dfb6642bc280ee8ef5ba90
This commit is contained in:
Ryan VanderMeulen 2015-06-19 10:56:48 -04:00
parent bd6c8de819
commit 1135142546
39 changed files with 708 additions and 1164 deletions

View File

@ -1785,7 +1785,8 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
}
} else {
// We're going to run these against some non-global scope.
if (!JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script)) {
options.setHasPollutedScope(true);
if (!JS::Compile(cx, options, srcBuf, &script)) {
return;
}
}

View File

@ -212,6 +212,18 @@ TryEvalJSON(JSContext* cx, JSLinearString* str, MutableHandleValue rval)
: ParseEvalStringAsJSON(cx, linearChars.twoByteRange(), rval);
}
static bool
HasPollutedScopeChain(JSObject* scopeChain)
{
while (scopeChain) {
if (scopeChain->is<DynamicWithObject>())
return true;
scopeChain = scopeChain->enclosingScope();
}
return false;
}
// Define subset of ExecuteType so that casting performs the injection.
enum EvalType { DIRECT_EVAL = EXECUTE_DIRECT_EVAL, INDIRECT_EVAL = EXECUTE_INDIRECT_EVAL };
@ -320,8 +332,13 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
if (!staticScope)
return false;
bool hasPollutedGlobalScope =
HasPollutedScopeChain(scopeobj) ||
(evalType == DIRECT_EVAL && callerScript->hasPollutedGlobalScope());
CompileOptions options(cx);
options.setFileAndLine(filename, 1)
.setHasPollutedScope(hasPollutedGlobalScope)
.setIsRunOnce(true)
.setForEval(true)
.setNoScriptRval(false)
@ -339,7 +356,7 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
: SourceBufferHolder::NoOwnership;
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
scopeobj, staticScope, callerScript,
scopeobj, callerScript, staticScope,
options, srcBuf, linearStr, staticLevel);
if (!compiled)
return false;
@ -393,7 +410,7 @@ js::DirectEvalStringFromIon(JSContext* cx,
bool mutedErrors;
uint32_t pcOffset;
DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
&mutedErrors, CALLED_FROM_JSOP_EVAL);
&mutedErrors, CALLED_FROM_JSOP_EVAL);
const char* introducerFilename = filename;
if (maybeScript && maybeScript->scriptSource()->introducerFilename())
@ -406,6 +423,8 @@ js::DirectEvalStringFromIon(JSContext* cx,
CompileOptions options(cx);
options.setFileAndLine(filename, 1)
.setHasPollutedScope(HasPollutedScopeChain(scopeobj) ||
callerScript->hasPollutedGlobalScope())
.setIsRunOnce(true)
.setForEval(true)
.setNoScriptRval(false)
@ -423,7 +442,7 @@ js::DirectEvalStringFromIon(JSContext* cx,
: SourceBufferHolder::NoOwnership;
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
scopeobj, staticScope, callerScript,
scopeobj, callerScript, staticScope,
options, srcBuf, linearStr, staticLevel);
if (!compiled)
return false;
@ -494,31 +513,35 @@ js::ExecuteInGlobalAndReturnScope(JSContext* cx, HandleObject global, HandleScri
CHECK_REQUEST(cx);
assertSameCompartment(cx, global);
MOZ_ASSERT(global->is<GlobalObject>());
MOZ_RELEASE_ASSERT(scriptArg->hasNonSyntacticScope());
MOZ_RELEASE_ASSERT(scriptArg->hasPollutedGlobalScope());
RootedScript script(cx, scriptArg);
if (script->compartment() != cx->compartment()) {
Rooted<ScopeObject*> staticScope(cx, StaticNonSyntacticScopeObjects::create(cx, nullptr));
if (!staticScope)
return false;
script = CloneGlobalScript(cx, staticScope, script);
script = CloneScript(cx, nullptr, nullptr, script);
if (!script)
return false;
Debugger::onNewScript(cx, script);
}
Rooted<GlobalObject*> globalRoot(cx, &global->as<GlobalObject>());
Rooted<ScopeObject*> scope(cx, NonSyntacticVariablesObject::create(cx, globalRoot));
RootedObject scope(cx, JS_NewPlainObject(cx));
if (!scope)
return false;
if (!scope->setQualifiedVarObj(cx))
return false;
if (!scope->setUnqualifiedVarObj(cx))
return false;
JSObject* thisobj = GetThisObject(cx, global);
if (!thisobj)
return false;
RootedValue thisv(cx, ObjectValue(*thisobj));
RootedValue rval(cx);
// XXXbz when this is fixed to pass in an actual ScopeObject, fix
// up the assert in js::CloneFunctionObject accordingly.
if (!ExecuteKernel(cx, script, *scope, thisv, UndefinedValue(), EXECUTE_GLOBAL,
NullFramePtr() /* evalInFrame */, rval.address()))
{

View File

@ -2272,10 +2272,11 @@ EvalReturningScope(JSContext* cx, unsigned argc, jsval* vp)
JS::CompileOptions options(cx);
options.setFileAndLine(filename.get(), lineno);
options.setNoScriptRval(true);
options.setHasPollutedScope(true);
JS::SourceBufferHolder srcBuf(src, srclen, JS::SourceBufferHolder::NoOwnership);
RootedScript script(cx);
if (!JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script))
if (!JS::Compile(cx, options, srcBuf, &script))
return false;
if (global) {

View File

@ -144,11 +144,10 @@ MaybeCheckEvalFreeVariables(ExclusiveContext* cxArg, HandleScript evalCaller, Ha
}
static inline bool
CanLazilyParse(ExclusiveContext* cx, HandleObject staticScope,
const ReadOnlyCompileOptions& options)
CanLazilyParse(ExclusiveContext* cx, const ReadOnlyCompileOptions& options)
{
return options.canLazilyParse &&
!HasNonSyntacticStaticScopeChain(staticScope) &&
!options.hasPollutedGlobalScope &&
!cx->compartment()->options().disableLazyParsing() &&
!cx->compartment()->options().discardSource() &&
!options.sourceIsLazy;
@ -211,8 +210,8 @@ frontend::CreateScriptSourceObject(ExclusiveContext* cx, const ReadOnlyCompileOp
JSScript*
frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject scopeChain,
Handle<ScopeObject*> enclosingStaticScope,
HandleScript evalCaller,
Handle<StaticEvalObject*> evalStaticScope,
const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf,
JSString* source_ /* = nullptr */,
@ -261,7 +260,7 @@ frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject sco
return nullptr;
}
bool canLazilyParse = CanLazilyParse(cx, enclosingStaticScope, options);
bool canLazilyParse = CanLazilyParse(cx, options);
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
if (canLazilyParse) {
@ -285,22 +284,22 @@ frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject sco
bool savedCallerFun = evalCaller && evalCaller->functionOrCallerFunction();
Directives directives(options.strictOption);
GlobalSharedContext globalsc(cx, directives, enclosingStaticScope, options.extraWarningsOption);
GlobalSharedContext globalsc(cx, directives, evalStaticScope, options.extraWarningsOption);
Rooted<JSScript*> script(cx, JSScript::Create(cx, enclosingStaticScope, savedCallerFun,
Rooted<JSScript*> script(cx, JSScript::Create(cx, evalStaticScope, savedCallerFun,
options, staticLevel, sourceObject, 0,
srcBuf.length()));
if (!script)
return nullptr;
bool insideNonGlobalEval =
enclosingStaticScope && enclosingStaticScope->is<StaticEvalObject>() &&
enclosingStaticScope->as<StaticEvalObject>().enclosingScopeForStaticScopeIter();
evalStaticScope && evalStaticScope->enclosingScopeForStaticScopeIter();
BytecodeEmitter::EmitterMode emitterMode =
options.selfHostingMode ? BytecodeEmitter::SelfHosting : BytecodeEmitter::Normal;
BytecodeEmitter bce(/* parent = */ nullptr, &parser, &globalsc, script,
/* lazyScript = */ nullptr, options.forEval,
evalCaller, insideNonGlobalEval, options.lineno, emitterMode);
evalCaller, insideNonGlobalEval,
options.lineno, emitterMode);
if (!bce.init())
return nullptr;
@ -562,7 +561,7 @@ CompileFunctionBody(JSContext* cx, MutableHandleFunction fun, const ReadOnlyComp
return false;
}
bool canLazilyParse = CanLazilyParse(cx, enclosingStaticScope, options);
bool canLazilyParse = CanLazilyParse(cx, options);
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
if (canLazilyParse) {

View File

@ -17,17 +17,18 @@ class AutoNameVector;
class LazyScript;
class LifoAlloc;
class ScriptSourceObject;
class ScopeObject;
class StaticEvalObject;
struct SourceCompressionTask;
namespace frontend {
JSScript*
CompileScript(ExclusiveContext* cx, LifoAlloc* alloc,
HandleObject scopeChain, Handle<ScopeObject*> enclosingStaticScope,
HandleScript evalCaller, const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf, JSString* source_ = nullptr,
unsigned staticLevel = 0, SourceCompressionTask* extraSct = nullptr);
HandleObject scopeChain, HandleScript evalCaller,
Handle<StaticEvalObject*> evalStaticScope,
const ReadOnlyCompileOptions& options, SourceBufferHolder& srcBuf,
JSString* source_ = nullptr, unsigned staticLevel = 0,
SourceCompressionTask* extraSct = nullptr);
bool
CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length);

View File

@ -769,7 +769,7 @@ BytecodeEmitter::enclosingStaticScope()
// Top-level eval scripts have a placeholder static scope so that
// StaticScopeIter may iterate through evals.
return sc->asGlobalSharedContext()->topStaticScope();
return sc->asGlobalSharedContext()->evalStaticScope();
}
return sc->asFunctionBox()->function();
@ -1548,14 +1548,14 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
// Use generic ops if a catch block is encountered.
return false;
}
if (ssi.hasSyntacticDynamicScopeObject())
if (ssi.hasDynamicScopeObject())
hops++;
continue;
}
RootedScript script(cx, ssi.funScript());
if (script->functionNonDelazifying()->atom() == pn->pn_atom)
return false;
if (ssi.hasSyntacticDynamicScopeObject()) {
if (ssi.hasDynamicScopeObject()) {
uint32_t slot;
if (lookupAliasedName(script, pn->pn_atom->asPropertyName(), &slot, pn)) {
JSOp op;
@ -1587,9 +1587,9 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
if (insideNonGlobalEval)
return false;
// Skip trying to use GNAME ops if we know our script has a non-syntactic
// scope, since they'll just get treated as NAME ops anyway.
if (script->hasNonSyntacticScope())
// Skip trying to use GNAME ops if we know our script has a polluted
// global scope, since they'll just get treated as NAME ops anyway.
if (script->hasPollutedGlobalScope())
return false;
// Deoptimized names also aren't necessarily globals.
@ -2356,14 +2356,13 @@ BytecodeEmitter::checkRunOnceContext()
bool
BytecodeEmitter::needsImplicitThis()
{
if (sc->inWith())
if (sc->isFunctionBox() && sc->asFunctionBox()->inWith)
return true;
for (StmtInfoBCE* stmt = topStmt; stmt; stmt = stmt->down) {
if (stmt->type == STMT_WITH)
return true;
}
return false;
}
@ -3407,19 +3406,6 @@ BytecodeEmitter::emitFunctionScript(ParseNode* body)
*/
FunctionBox* funbox = sc->asFunctionBox();
// Link the function and the script to each other, so that StaticScopeIter
// may walk the scope chain of currently compiling scripts.
RootedFunction fun(cx, funbox->function());
MOZ_ASSERT(fun->isInterpreted());
script->setFunction(fun);
if (fun->isInterpretedLazy())
fun->setUnlazifiedScript(script);
else
fun->setScript(script);
if (funbox->argumentsHasLocalBinding()) {
MOZ_ASSERT(offset() == 0); /* See JSScript::argumentsBytecode. */
switchToPrologue();
@ -3523,6 +3509,15 @@ BytecodeEmitter::emitFunctionScript(ParseNode* body)
MOZ_ASSERT(!script->hasRunOnce());
}
/* Initialize fun->script() so that the debugger has a valid fun->script(). */
RootedFunction fun(cx, script->functionNonDelazifying());
MOZ_ASSERT(fun->isInterpreted());
if (fun->isInterpretedLazy())
fun->setUnlazifiedScript(script);
else
fun->setScript(script);
tellDebuggerAboutCompiledScript(cx);
return true;
@ -5770,6 +5765,8 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
Rooted<JSScript*> parent(cx, script);
CompileOptions options(cx, parser->options());
options.setMutedErrors(parent->mutedErrors())
.setHasPollutedScope(parent->hasPollutedGlobalScope())
.setSelfHostingMode(parent->selfHosted())
.setNoScriptRval(false)
.setForEval(false)
.setVersion(parent->getVersion());

View File

@ -22,7 +22,7 @@
namespace js {
class ScopeObject;
class StaticEvalObject;
namespace frontend {

View File

@ -596,7 +596,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
bufEnd(0),
length(0),
generatorKindBits_(GeneratorKindAsBits(generatorKind)),
inWith_(false), // initialized below
inWith(false), // initialized below
inGenexpLambda(false),
hasDestructuringArgs(false),
useAsm(false),
@ -612,7 +612,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
MOZ_ASSERT(fun->isTenured());
if (!outerpc) {
inWith_ = false;
inWith = false;
} else if (outerpc->parsingWith) {
// This covers cases that don't involve eval(). For example:
@ -621,7 +621,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
//
// In this case, |outerpc| corresponds to global code, and
// outerpc->parsingWith is true.
inWith_ = true;
inWith = true;
} else if (outerpc->sc->isFunctionBox()) {
// This is like the above case, but for more deeply nested functions.
@ -632,17 +632,8 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
// In this case, the inner anonymous function needs to inherit the
// setting of |inWith| from the outer one.
FunctionBox* parent = outerpc->sc->asFunctionBox();
if (parent && parent->inWith())
inWith_ = true;
} else {
// This is like the above case, but when inside eval.
//
// For example:
//
// with(o) { eval("(function() { g(); })();"); }
//
// In this case, the static scope chain tells us the presence of with.
inWith_ = outerpc->sc->inWith();
if (parent && parent->inWith)
inWith = true;
}
}
@ -2241,7 +2232,7 @@ Parser<SyntaxParseHandler>::finishFunctionDefinition(Node pn, FunctionBox* funbo
// while its ParseContext and associated lexdeps and inner functions are
// still available.
if (funbox->inWith())
if (funbox->inWith)
return abortIfSyntaxParser();
size_t numFreeVariables = pc->lexdeps->count();

View File

@ -237,7 +237,6 @@ class SharedContext
SuperProperty
};
virtual bool allowSyntax(AllowedSyntax allowed) const = 0;
virtual bool inWith() const = 0;
protected:
static bool FunctionAllowsSyntax(JSFunction* func, AllowedSyntax allowed)
@ -259,13 +258,21 @@ class SharedContext
class GlobalSharedContext : public SharedContext
{
private:
Handle<ScopeObject*> topStaticScope_;
bool allowNewTarget_;
bool allowSuperProperty_;
bool inWith_;
Handle<StaticEvalObject*> staticEvalScope_;
bool computeAllowSyntax(AllowedSyntax allowed) const {
StaticScopeIter<CanGC> it(context, topStaticScope_);
public:
GlobalSharedContext(ExclusiveContext* cx,
Directives directives, Handle<StaticEvalObject*> staticEvalScope,
bool extraWarnings)
: SharedContext(cx, directives, extraWarnings),
staticEvalScope_(staticEvalScope)
{}
ObjectBox* toObjectBox() { return nullptr; }
HandleObject evalStaticScope() const { return staticEvalScope_; }
bool allowSyntax(AllowedSyntax allowed) const {
StaticScopeIter<CanGC> it(context, staticEvalScope_);
for (; !it.done(); it++) {
if (it.type() == StaticScopeIter<CanGC>::Function &&
!it.fun().isArrow())
@ -275,40 +282,6 @@ class GlobalSharedContext : public SharedContext
}
return false;
}
bool computeInWith() const {
for (StaticScopeIter<CanGC> it(context, topStaticScope_); !it.done(); it++) {
if (it.type() == StaticScopeIter<CanGC>::With)
return true;
}
return false;
}
public:
GlobalSharedContext(ExclusiveContext* cx,
Directives directives, Handle<ScopeObject*> topStaticScope,
bool extraWarnings)
: SharedContext(cx, directives, extraWarnings),
topStaticScope_(topStaticScope),
allowNewTarget_(computeAllowSyntax(AllowedSyntax::NewTarget)),
allowSuperProperty_(computeAllowSyntax(AllowedSyntax::SuperProperty)),
inWith_(computeInWith())
{}
ObjectBox* toObjectBox() override { return nullptr; }
HandleObject topStaticScope() const { return topStaticScope_; }
bool allowSyntax(AllowedSyntax allowSyntax) const override {
switch (allowSyntax) {
case AllowedSyntax::NewTarget:
// Any function supports new.target
return allowNewTarget_;
case AllowedSyntax::SuperProperty:
return allowSuperProperty_;
default:;
}
MOZ_CRASH("Unknown AllowedSyntax query");
}
bool inWith() const override { return inWith_; }
};
class FunctionBox : public ObjectBox, public SharedContext
@ -322,7 +295,7 @@ class FunctionBox : public ObjectBox, public SharedContext
uint16_t length;
uint8_t generatorKindBits_; /* The GeneratorKind of this function. */
bool inWith_:1; /* some enclosing scope is a with-statement */
bool inWith:1; /* some enclosing scope is a with-statement */
bool inGenexpLambda:1; /* lambda from generator expression */
bool hasDestructuringArgs:1; /* arguments list contains destructuring expression */
bool useAsm:1; /* see useAsmOrInsideUseAsm */
@ -340,7 +313,7 @@ class FunctionBox : public ObjectBox, public SharedContext
ParseContext<ParseHandler>* pc, Directives directives,
bool extraWarnings, GeneratorKind generatorKind);
ObjectBox* toObjectBox() override { return this; }
ObjectBox* toObjectBox() { return this; }
JSFunction* function() const { return &object->as<JSFunction>(); }
GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
@ -404,13 +377,9 @@ class FunctionBox : public ObjectBox, public SharedContext
isGenerator();
}
bool allowSyntax(AllowedSyntax allowed) const override {
bool allowSyntax(AllowedSyntax allowed) const {
return FunctionAllowsSyntax(function(), allowed);
}
bool inWith() const override {
return inWith_;
}
};
inline FunctionBox*

View File

@ -4,7 +4,6 @@ var g = newGlobal();
var g2 = newGlobal();
var dbg = new Debugger(g, g2);
var log = '';
var canary = 42;
dbg.onNewScript = function (evalScript) {
log += 'e';
@ -25,8 +24,5 @@ dbg.onDebuggerStatement = function (frame) {
};
assertEq(log, '');
var evalScope = g.evalReturningScope("canary = 'dead'; debugger; // nee", g2);
var evalScope = g.evalReturningScope("debugger; // nee", g2);
assertEq(log, 'ecbd');
assertEq(canary, 42);
assertEq(evalScope.canary, 'dead');

View File

@ -704,14 +704,13 @@ InitFromBailout(JSContext* cx, HandleScript caller, jsbytecode* callerPC,
scopeChain = fun->environment();
}
} else {
// For global scripts without a non-syntactic scope the scope
// For global scripts without a polluted global scope the scope
// chain is the script's global (Ion does not compile scripts
// with a non-syntactic global scope). Also note that it's
// invalid to resume into the prologue in this case because
// the prologue expects the scope chain in R1 for eval and
// global scripts.
// with a polluted global scope). Also note that it's invalid to
// resume into the prologue in this case because the prologue
// expects the scope chain in R1 for eval and global scripts.
MOZ_ASSERT(!script->isForEval());
MOZ_ASSERT(!script->hasNonSyntacticScope());
MOZ_ASSERT(!script->hasPollutedGlobalScope());
scopeChain = &(script->global());
}
}

View File

@ -20,7 +20,6 @@
#endif
#include "jit/SharedICHelpers.h"
#include "jit/VMFunctions.h"
#include "vm/ScopeObject.h"
#include "vm/TraceLogging.h"
#include "jsscriptinlines.h"
@ -129,7 +128,7 @@ BaselineCompiler::compile()
return Method_Error;
if (fun->isNamedLambda()) {
RootedObject declEnvObject(cx, DeclEnvObject::createTemplateObject(cx, fun, TenuredObject));
RootedObject declEnvObject(cx, DeclEnvObject::createTemplateObject(cx, fun, gc::TenuredHeap));
if (!declEnvObject)
return Method_Error;
templateScope->as<ScopeObject>().setEnclosingScope(declEnvObject);
@ -2063,7 +2062,7 @@ BaselineCompiler::emit_JSOP_IN()
bool
BaselineCompiler::emit_JSOP_GETGNAME()
{
if (script->hasNonSyntacticScope())
if (script->hasPollutedGlobalScope())
return emit_JSOP_GETNAME();
RootedPropertyName name(cx, script->getName(pc));
@ -2098,7 +2097,7 @@ BaselineCompiler::emit_JSOP_GETGNAME()
bool
BaselineCompiler::emit_JSOP_BINDGNAME()
{
if (!script->hasNonSyntacticScope()) {
if (!script->hasPollutedGlobalScope()) {
frame.push(ObjectValue(script->global()));
return true;
}
@ -2921,7 +2920,7 @@ BaselineCompiler::emit_JSOP_IMPLICITTHIS()
bool
BaselineCompiler::emit_JSOP_GIMPLICITTHIS()
{
if (!script->hasNonSyntacticScope()) {
if (!script->hasPollutedGlobalScope()) {
frame.push(UndefinedValue());
return true;
}

View File

@ -6133,7 +6133,7 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_
attached = true;
}
if (!attached && IsGlobalOp(JSOp(*pc)) && !script->hasNonSyntacticScope()) {
if (!attached && IsGlobalOp(JSOp(*pc)) && !script->hasPollutedGlobalScope()) {
if (!TryAttachGlobalNameAccessorStub(cx, script, pc, stub, scopeChain.as<GlobalObject>(),
name, &attached, &isTemporarilyUnoptimizable))
{
@ -6163,7 +6163,7 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_
if (attached)
return true;
if (IsGlobalOp(JSOp(*pc)) && !script->hasNonSyntacticScope()) {
if (IsGlobalOp(JSOp(*pc)) && !script->hasPollutedGlobalScope()) {
Handle<GlobalObject*> global = scopeChain.as<GlobalObject>();
if (!TryAttachGlobalNameValueStub(cx, script, pc, stub, global, name, &attached))
return false;

View File

@ -170,7 +170,7 @@ BytecodeAnalysis::init(TempAllocator& alloc, GSNCache& gsn)
case JSOP_GETGNAME:
case JSOP_SETGNAME:
case JSOP_STRICTSETGNAME:
if (script_->hasNonSyntacticScope())
if (script_->hasPollutedGlobalScope())
usesScopeChain_ = true;
break;

View File

@ -4686,7 +4686,7 @@ CodeGenerator::visitSimdUnbox(LSimdUnbox* lir)
bailoutFrom(&bail, lir->snapshot());
}
typedef js::DeclEnvObject* (*NewDeclEnvObjectFn)(JSContext*, HandleFunction, NewObjectKind);
typedef js::DeclEnvObject* (*NewDeclEnvObjectFn)(JSContext*, HandleFunction, gc::InitialHeap);
static const VMFunction NewDeclEnvObjectInfo =
FunctionInfo<NewDeclEnvObjectFn>(DeclEnvObject::createTemplateObject);
@ -4700,7 +4700,7 @@ CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject* lir)
// If we have a template object, we can inline call object creation.
OutOfLineCode* ool = oolCallVM(NewDeclEnvObjectInfo, lir,
ArgList(ImmGCPtr(info.funMaybeLazy()), Imm32(GenericObject)),
ArgList(ImmGCPtr(info.funMaybeLazy()), Imm32(gc::DefaultHeap)),
StoreRegisterTo(objReg));
bool initContents = ShouldInitFixedSlots(lir, templateObj);

View File

@ -2173,12 +2173,12 @@ CheckScript(JSContext* cx, JSScript* script, bool osr)
return false;
}
if (script->hasNonSyntacticScope() && !script->functionNonDelazifying()) {
// Support functions with a non-syntactic global scope but not other
if (script->hasPollutedGlobalScope() && !script->functionNonDelazifying()) {
// Support functions with a polluted global scope but not other
// scripts. For global scripts, IonBuilder currently uses the global
// object as scope chain, this is not valid when the script has a
// non-syntactic global scope.
TrackAndSpewIonAbort(cx, script, "has non-syntactic global scope");
// polluted global scope.
TrackAndSpewIonAbort(cx, script, "has polluted global scope");
return false;
}

View File

@ -618,7 +618,7 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock* entry, jsbytecode* start, jsbytecod
type = MIRType_Undefined;
break;
case JSOP_GIMPLICITTHIS:
if (!script()->hasNonSyntacticScope())
if (!script()->hasPollutedGlobalScope())
type = MIRType_Undefined;
break;
case JSOP_NULL:
@ -1182,10 +1182,10 @@ IonBuilder::initScopeChain(MDefinition* callee)
return false;
}
} else {
// For global scripts without a non-syntactic global scope, the scope
// chain is the global object.
// For global scripts without a polluted global scope, the scope chain
// is the global object.
MOZ_ASSERT(!script()->isForEval());
MOZ_ASSERT(!script()->hasNonSyntacticScope());
MOZ_ASSERT(!script()->hasPollutedGlobalScope());
scope = constant(ObjectValue(script()->global()));
}
@ -1800,7 +1800,7 @@ IonBuilder::inspectOpcode(JSOp op)
case JSOP_GETGNAME:
{
PropertyName* name = info().getAtom(pc)->asPropertyName();
if (!script()->hasNonSyntacticScope())
if (!script()->hasPollutedGlobalScope())
return jsop_getgname(name);
return jsop_getname(name);
}
@ -1809,7 +1809,7 @@ IonBuilder::inspectOpcode(JSOp op)
case JSOP_STRICTSETGNAME:
{
PropertyName* name = info().getAtom(pc)->asPropertyName();
if (script()->hasNonSyntacticScope())
if (script()->hasPollutedGlobalScope())
return jsop_setprop(name);
JSObject* obj = &script()->global();
return setStaticName(obj, name);
@ -1828,7 +1828,7 @@ IonBuilder::inspectOpcode(JSOp op)
}
case JSOP_BINDGNAME:
if (!script()->hasNonSyntacticScope())
if (!script()->hasPollutedGlobalScope())
return pushConstant(ObjectValue(script()->global()));
// Fall through to JSOP_BINDNAME
case JSOP_BINDNAME:
@ -1975,7 +1975,7 @@ IonBuilder::inspectOpcode(JSOp op)
return jsop_debugger();
case JSOP_GIMPLICITTHIS:
if (!script()->hasNonSyntacticScope())
if (!script()->hasPollutedGlobalScope())
return pushConstant(UndefinedValue());
// Just fall through to the unsupported bytecode case.
@ -7613,7 +7613,7 @@ bool
IonBuilder::jsop_getname(PropertyName* name)
{
MDefinition* object;
if (IsGlobalOp(JSOp(*pc)) && !script()->hasNonSyntacticScope()) {
if (IsGlobalOp(JSOp(*pc)) && !script()->hasPollutedGlobalScope()) {
MInstruction* global = constant(ObjectValue(script()->global()));
object = global;
} else {

View File

@ -2553,7 +2553,7 @@ InlineFrameIterator::computeScopeChain(Value scopeChainValue, MaybeReadFallback&
// Ion does not handle non-function scripts that have anything other than
// the global on their scope chain.
MOZ_ASSERT(!script()->isForEval());
MOZ_ASSERT(!script()->hasNonSyntacticScope());
MOZ_ASSERT(!script()->hasPollutedGlobalScope());
return &script()->global();
}

View File

@ -3299,22 +3299,12 @@ JS::GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id
}
static bool
CreateNonSyntacticScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
MutableHandleObject dynamicScopeObj,
MutableHandle<ScopeObject*> staticScopeObj)
CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
MutableHandleObject dynamicScopeObj,
MutableHandleObject staticScopeObj)
{
if (!js::CreateScopeObjectsForScopeChain(cx, scopeChain, cx->global(), dynamicScopeObj))
return false;
if (scopeChain.empty()) {
staticScopeObj.set(nullptr);
} else {
staticScopeObj.set(StaticNonSyntacticScopeObjects::create(cx, nullptr));
if (!staticScopeObj)
return false;
}
return true;
return js::CreateScopeObjectsForScopeChain(cx, scopeChain, cx->global(),
dynamicScopeObj, staticScopeObj);
}
static bool
@ -3325,23 +3315,11 @@ IsFunctionCloneable(HandleFunction fun, HandleObject dynamicScope)
// If a function was compiled to be lexically nested inside some other
// script, we cannot clone it without breaking the compiler's assumptions.
if (JSObject* scope = fun->nonLazyScript()->enclosingStaticScope()) {
// If the script already deals with a non-syntactic scope, we can clone
// it.
if (scope->is<StaticNonSyntacticScopeObjects>())
return true;
// If the script is an indirect eval that is immediately scoped under
// the global, we can clone it.
if (scope->is<StaticEvalObject>() &&
!scope->as<StaticEvalObject>().isDirect() &&
!scope->as<StaticEvalObject>().isStrict())
{
return true;
}
// Any other enclosing static scope (e.g., function, block) cannot be
// cloned.
JSObject* scope = fun->nonLazyScript()->enclosingStaticScope();
if (scope && (!scope->is<StaticEvalObject>() ||
scope->as<StaticEvalObject>().isDirect() ||
scope->as<StaticEvalObject>().isStrict()))
{
return false;
}
@ -3349,8 +3327,7 @@ IsFunctionCloneable(HandleFunction fun, HandleObject dynamicScope)
}
static JSObject*
CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject dynamicScope,
Handle<ScopeObject*> staticScope)
CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject dynamicScope)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
@ -3387,21 +3364,7 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject dynamicScop
return nullptr;
}
if (CanReuseScriptForClone(cx->compartment(), fun, dynamicScope)) {
// If the script is to be reused, either the script can already handle
// non-syntactic scopes, or there is no new static scope.
#ifdef DEBUG
// Fail here if we OOM during debug asserting.
// CloneFunctionReuseScript will delazify the script anyways, so we
// are not creating an extra failure condition for DEBUG builds.
if (!fun->getOrCreateScript(cx))
return nullptr;
MOZ_ASSERT(!staticScope || fun->nonLazyScript()->hasNonSyntacticScope());
#endif
return CloneFunctionReuseScript(cx, fun, dynamicScope, fun->getAllocKind());
}
return CloneFunctionAndScript(cx, fun, dynamicScope, staticScope, fun->getAllocKind());
return CloneFunctionObject(cx, fun, dynamicScope, fun->getAllocKind());
}
namespace JS {
@ -3409,18 +3372,18 @@ namespace JS {
JS_PUBLIC_API(JSObject*)
CloneFunctionObject(JSContext* cx, JS::Handle<JSObject*> funobj)
{
return CloneFunctionObject(cx, funobj, cx->global(), /* staticScope = */ nullptr);
return CloneFunctionObject(cx, funobj, cx->global());
}
extern JS_PUBLIC_API(JSObject*)
CloneFunctionObject(JSContext* cx, HandleObject funobj, AutoObjectVector& scopeChain)
{
RootedObject dynamicScope(cx);
Rooted<ScopeObject*> staticScope(cx);
if (!CreateNonSyntacticScopeChain(cx, scopeChain, &dynamicScope, &staticScope))
RootedObject unusedStaticScope(cx);
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, &dynamicScope, &unusedStaticScope))
return nullptr;
return CloneFunctionObject(cx, funobj, dynamicScope, staticScope);
return CloneFunctionObject(cx, funobj, dynamicScope);
}
} // namespace JS
@ -3890,40 +3853,31 @@ JS::CompileOptions::CompileOptions(JSContext* cx, JSVersion version)
asmJSOption = cx->runtime()->options().asmJS();
}
enum SyntacticScopeOption { HasSyntacticScope, HasNonSyntacticScope };
static bool
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOption scopeOption,
SourceBufferHolder& srcBuf, MutableHandleScript script)
bool
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf, MutableHandleScript script)
{
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
AutoLastFrameCheck lfc(cx);
Rooted<ScopeObject*> staticScope(cx);
if (scopeOption == HasNonSyntacticScope) {
staticScope = StaticNonSyntacticScopeObjects::create(cx, nullptr);
if (!staticScope)
return false;
}
script.set(frontend::CompileScript(cx, &cx->tempLifoAlloc(), cx->global(),
staticScope, nullptr, options, srcBuf));
nullptr, nullptr, options, srcBuf));
return !!script;
}
static bool
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOption scopeOption,
const char16_t* chars, size_t length, MutableHandleScript script)
bool
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length, MutableHandleScript script)
{
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
return ::Compile(cx, options, scopeOption, srcBuf, script);
return Compile(cx, options, srcBuf, script);
}
static bool
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOption scopeOption,
const char* bytes, size_t length, MutableHandleScript script)
bool
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
const char* bytes, size_t length, MutableHandleScript script)
{
mozilla::UniquePtr<char16_t, JS::FreePolicy> chars;
if (options.utf8)
@ -3933,101 +3887,30 @@ Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOpti
if (!chars)
return false;
return ::Compile(cx, options, scopeOption, chars.get(), length, script);
return Compile(cx, options, chars.get(), length, script);
}
static bool
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOption scopeOption,
FILE* fp, MutableHandleScript script)
bool
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options, FILE* fp,
MutableHandleScript script)
{
FileContents buffer(cx);
if (!ReadCompleteFile(cx, fp, buffer))
return false;
return ::Compile(cx, options, scopeOption, buffer.begin(), buffer.length(), script);
return Compile(cx, options, buffer.begin(), buffer.length(), script);
}
static bool
Compile(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, SyntacticScopeOption scopeOption,
const char* filename, MutableHandleScript script)
bool
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, const char* filename,
MutableHandleScript script)
{
AutoFile file;
if (!file.open(cx, filename))
return false;
CompileOptions options(cx, optionsArg);
options.setFileAndLine(filename, 1);
return ::Compile(cx, options, scopeOption, file.fp(), script);
}
bool
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
{
return ::Compile(cx, options, HasSyntacticScope, srcBuf, script);
}
bool
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
const char* bytes, size_t length, JS::MutableHandleScript script)
{
return ::Compile(cx, options, HasSyntacticScope, bytes, length, script);
}
bool
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length, JS::MutableHandleScript script)
{
return ::Compile(cx, options, HasSyntacticScope, chars, length, script);
}
bool
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
FILE* file, JS::MutableHandleScript script)
{
return ::Compile(cx, options, HasSyntacticScope, file, script);
}
bool
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
const char* filename, JS::MutableHandleScript script)
{
return ::Compile(cx, options, HasSyntacticScope, filename, script);
}
bool
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
{
return ::Compile(cx, options, HasNonSyntacticScope, srcBuf, script);
}
bool
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
const char* bytes, size_t length, JS::MutableHandleScript script)
{
return ::Compile(cx, options, HasNonSyntacticScope, bytes, length, script);
}
bool
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length,
JS::MutableHandleScript script)
{
return ::Compile(cx, options, HasNonSyntacticScope, chars, length, script);
}
bool
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
FILE* file, JS::MutableHandleScript script)
{
return ::Compile(cx, options, HasNonSyntacticScope, file, script);
}
bool
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
const char* filename, JS::MutableHandleScript script)
{
return ::Compile(cx, options, HasNonSyntacticScope, filename, script);
return Compile(cx, options, file.fp(), script);
}
JS_PUBLIC_API(bool)
@ -4210,13 +4093,13 @@ CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
if (!fun)
return false;
// Make sure the static scope chain matches up when we have a
// non-syntactic scope.
MOZ_ASSERT_IF(!enclosingDynamicScope->is<GlobalObject>(),
HasNonSyntacticStaticScopeChain(enclosingStaticScope));
// Make sure to handle cases when we have a polluted scopechain.
CompileOptions options(cx, optionsArg);
if (!frontend::CompileFunctionBody(cx, fun, options, formals, srcBuf, enclosingStaticScope))
if (!enclosingDynamicScope->is<GlobalObject>())
options.setHasPollutedScope(true);
if (!frontend::CompileFunctionBody(cx, fun, options, formals, srcBuf,
enclosingStaticScope))
return false;
return true;
@ -4229,8 +4112,8 @@ JS::CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
SourceBufferHolder& srcBuf, MutableHandleFunction fun)
{
RootedObject dynamicScopeObj(cx);
Rooted<ScopeObject*> staticScopeObj(cx);
if (!CreateNonSyntacticScopeChain(cx, scopeChain, &dynamicScopeObj, &staticScopeObj))
RootedObject staticScopeObj(cx);
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, &dynamicScopeObj, &staticScopeObj))
return false;
return CompileFunction(cx, options, name, nargs, argnames,
@ -4304,34 +4187,33 @@ JS_DecompileFunctionBody(JSContext* cx, HandleFunction fun, unsigned indent)
}
MOZ_NEVER_INLINE static bool
ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, jsval* rval)
ExecuteScript(JSContext* cx, HandleObject obj, HandleScript scriptArg, jsval* rval)
{
RootedScript script(cx, scriptArg);
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, scope, script);
MOZ_ASSERT_IF(!scope->is<GlobalObject>(), script->hasNonSyntacticScope());
assertSameCompartment(cx, obj, scriptArg);
if (!script->hasPollutedGlobalScope() && !obj->is<GlobalObject>()) {
script = CloneScript(cx, nullptr, nullptr, script, HasPollutedGlobalScope);
if (!script)
return false;
js::Debugger::onNewScript(cx, script);
}
AutoLastFrameCheck lfc(cx);
return Execute(cx, script, *scope, rval);
return Execute(cx, script, *obj, rval);
}
static bool
ExecuteScript(JSContext* cx, AutoObjectVector& scopeChain, HandleScript scriptArg, jsval* rval)
{
RootedObject dynamicScope(cx);
Rooted<ScopeObject*> staticScope(cx);
if (!CreateNonSyntacticScopeChain(cx, scopeChain, &dynamicScope, &staticScope))
RootedObject unusedStaticScope(cx);
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, &dynamicScope, &unusedStaticScope))
return false;
RootedScript script(cx, scriptArg);
if (!script->hasNonSyntacticScope() && !dynamicScope->is<GlobalObject>()) {
script = CloneGlobalScript(cx, staticScope, script);
if (!script)
return false;
js::Debugger::onNewScript(cx, script);
}
return ExecuteScript(cx, dynamicScope, script, rval);
return ExecuteScript(cx, dynamicScope, scriptArg, rval);
}
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
@ -4365,7 +4247,7 @@ JS::CloneAndExecuteScript(JSContext* cx, HandleScript scriptArg)
CHECK_REQUEST(cx);
RootedScript script(cx, scriptArg);
if (script->compartment() != cx->compartment()) {
script = CloneGlobalScript(cx, /* enclosingScope = */ nullptr, script);
script = CloneScript(cx, nullptr, nullptr, script);
if (!script)
return false;
@ -4377,8 +4259,7 @@ JS::CloneAndExecuteScript(JSContext* cx, HandleScript scriptArg)
static const unsigned LARGE_SCRIPT_LENGTH = 500*1024;
static bool
Evaluate(JSContext* cx, HandleObject scope, Handle<ScopeObject*> staticScope,
const ReadOnlyCompileOptions& optionsArg,
Evaluate(JSContext* cx, HandleObject scope, const ReadOnlyCompileOptions& optionsArg,
SourceBufferHolder& srcBuf, MutableHandleValue rval)
{
CompileOptions options(cx, optionsArg);
@ -4389,14 +4270,12 @@ Evaluate(JSContext* cx, HandleObject scope, Handle<ScopeObject*> staticScope,
AutoLastFrameCheck lfc(cx);
MOZ_ASSERT_IF(!scope->is<GlobalObject>(), HasNonSyntacticStaticScopeChain(staticScope));
options.setHasPollutedScope(!scope->is<GlobalObject>());
options.setIsRunOnce(true);
SourceCompressionTask sct(cx);
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(),
scope, staticScope,
/* evalCaller = */ nullptr, options,
srcBuf, /* source = */ nullptr, 0, &sct));
scope, nullptr, nullptr, options,
srcBuf, nullptr, 0, &sct));
if (!script)
return false;
@ -4426,10 +4305,10 @@ Evaluate(JSContext* cx, AutoObjectVector& scopeChain, const ReadOnlyCompileOptio
SourceBufferHolder& srcBuf, MutableHandleValue rval)
{
RootedObject dynamicScope(cx);
Rooted<ScopeObject*> staticScope(cx);
if (!CreateNonSyntacticScopeChain(cx, scopeChain, &dynamicScope, &staticScope))
RootedObject unusedStaticScope(cx);
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, &dynamicScope, &unusedStaticScope))
return false;
return ::Evaluate(cx, dynamicScope, staticScope, optionsArg, srcBuf, rval);
return ::Evaluate(cx, dynamicScope, optionsArg, srcBuf, rval);
}
static bool
@ -4437,7 +4316,7 @@ Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
const char16_t* chars, size_t length, MutableHandleValue rval)
{
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
return ::Evaluate(cx, cx->global(), nullptr, optionsArg, srcBuf, rval);
return ::Evaluate(cx, cx->global(), optionsArg, srcBuf, rval);
}
extern JS_PUBLIC_API(bool)
@ -4453,7 +4332,7 @@ JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
return false;
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
bool ok = ::Evaluate(cx, cx->global(), nullptr, options, srcBuf, rval);
bool ok = ::Evaluate(cx, cx->global(), options, srcBuf, rval);
return ok;
}
@ -4477,7 +4356,7 @@ JS_PUBLIC_API(bool)
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
SourceBufferHolder& srcBuf, MutableHandleValue rval)
{
return ::Evaluate(cx, cx->global(), nullptr, optionsArg, srcBuf, rval);
return ::Evaluate(cx, cx->global(), optionsArg, srcBuf, rval);
}
JS_PUBLIC_API(bool)

View File

@ -3465,6 +3465,7 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
utf8(false),
lineno(1),
column(0),
hasPollutedGlobalScope(false),
isRunOnce(false),
forEval(false),
noScriptRval(false),
@ -3504,6 +3505,7 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
bool utf8;
unsigned lineno;
unsigned column;
bool hasPollutedGlobalScope;
// isRunOnce only applies to non-function scripts.
bool isRunOnce;
bool forEval;
@ -3596,6 +3598,7 @@ class JS_FRIEND_API(OwningCompileOptions) : public ReadOnlyCompileOptions
}
OwningCompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
OwningCompileOptions& setColumn(unsigned c) { column = c; return *this; }
OwningCompileOptions& setHasPollutedScope(bool p) { hasPollutedGlobalScope = p; return *this; }
OwningCompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
OwningCompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
OwningCompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
@ -3679,6 +3682,7 @@ class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOpti
}
CompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
CompileOptions& setColumn(unsigned c) { column = c; return *this; }
CompileOptions& setHasPollutedScope(bool p) { hasPollutedGlobalScope = p; return *this; }
CompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
CompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
CompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
@ -3722,32 +3726,12 @@ Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length, JS::MutableHandleScript script);
extern JS_PUBLIC_API(bool)
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
FILE* file, JS::MutableHandleScript script);
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, FILE* file,
JS::MutableHandleScript script);
extern JS_PUBLIC_API(bool)
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
const char* filename, JS::MutableHandleScript script);
extern JS_PUBLIC_API(bool)
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
extern JS_PUBLIC_API(bool)
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
const char* bytes, size_t length, JS::MutableHandleScript script);
extern JS_PUBLIC_API(bool)
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length, JS::MutableHandleScript script);
extern JS_PUBLIC_API(bool)
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
FILE* file, JS::MutableHandleScript script);
extern JS_PUBLIC_API(bool)
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
const char* filename, JS::MutableHandleScript script);
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, const char* filename,
JS::MutableHandleScript script);
extern JS_PUBLIC_API(bool)
CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);

View File

@ -35,7 +35,6 @@
#include "jit/JitFrameIterator.h"
#include "js/CallNonGenericMethod.h"
#include "js/Proxy.h"
#include "vm/Debugger.h"
#include "vm/GlobalObject.h"
#include "vm/Interpreter.h"
#include "vm/Shape.h"
@ -525,7 +524,7 @@ js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleObject enclosingScope, Han
HasSingletonType = 0x8
};
/* NB: Keep this in sync with CloneInnerInterpretedFunction. */
/* NB: Keep this in sync with CloneFunctionAndScript. */
RootedAtom atom(xdr->cx());
uint32_t firstword = 0; /* bitmask of FirstWordFlag */
uint32_t flagsword = 0; /* word for argument count and fun->flags */
@ -616,9 +615,10 @@ js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleObject enclosingScope, Han
fun->setFlags(uint16_t(flagsword));
fun->initAtom(atom);
if (firstword & IsLazy) {
MOZ_ASSERT(fun->lazyScript() == lazy);
fun->initLazyScript(lazy);
} else {
MOZ_ASSERT(fun->nonLazyScript() == script);
fun->initScript(script);
script->setFunction(fun);
MOZ_ASSERT(fun->nargs() == script->bindings.numArgs());
}
@ -637,6 +637,44 @@ js::XDRInterpretedFunction(XDRState<XDR_ENCODE>*, HandleObject, HandleScript, Mu
template bool
js::XDRInterpretedFunction(XDRState<XDR_DECODE>*, HandleObject, HandleScript, MutableHandleFunction);
JSObject*
js::CloneFunctionAndScript(JSContext* cx, HandleObject enclosingScope, HandleFunction srcFun,
PollutedGlobalScopeOption polluted)
{
/* NB: Keep this in sync with XDRInterpretedFunction. */
RootedObject cloneProto(cx);
if (srcFun->isStarGenerator()) {
cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
if (!cloneProto)
return nullptr;
}
gc::AllocKind allocKind = srcFun->getAllocKind();
RootedFunction clone(cx, NewFunctionWithProto(cx, nullptr, 0,
JSFunction::INTERPRETED, nullptr, nullptr,
cloneProto, allocKind, TenuredObject));
if (!clone)
return nullptr;
JSScript::AutoDelazify srcScript(cx, srcFun);
if (!srcScript)
return nullptr;
RootedScript clonedScript(cx, CloneScript(cx, enclosingScope, clone, srcScript, polluted));
if (!clonedScript)
return nullptr;
clone->setArgCount(srcFun->nargs());
clone->setFlags(srcFun->flags());
clone->initAtom(srcFun->displayAtom());
clone->initScript(clonedScript);
clonedScript->setFunction(clone);
if (!JSFunction::setTypeForScriptedFunction(cx, clone))
return nullptr;
RootedScript cloneScript(cx, clone->nonLazyScript());
return clone;
}
/*
* [[HasInstance]] internal method for Function objects: fetch the .prototype
* property of its 'this' parameter, and walks the prototype chain of v (only
@ -790,7 +828,7 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
/*
* The default 'new' group of Function.prototype is required by type
* inference to have unknown properties, to simplify handling of e.g.
* NewFunctionClone.
* CloneFunctionObject.
*/
if (!JSObject::setNewGroupUnknown(cx, &JSFunction::class_, functionProto))
return nullptr;
@ -1385,13 +1423,16 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
if (script) {
RootedObject enclosingScope(cx, lazy->enclosingScope());
RootedScript clonedScript(cx, CloneScriptIntoFunction(cx, enclosingScope, fun, script));
RootedScript clonedScript(cx, CloneScript(cx, enclosingScope, fun, script));
if (!clonedScript)
return false;
clonedScript->setSourceObject(lazy->sourceObject());
fun->initAtom(script->functionNonDelazifying()->displayAtom());
clonedScript->setFunction(fun);
fun->setUnlazifiedScript(clonedScript);
if (!lazy->maybeScript())
lazy->initScript(clonedScript);
@ -1978,20 +2019,6 @@ js::NewScriptedFunction(ExclusiveContext* cx, unsigned nargs,
atom, nullptr, allocKind, newKind);
}
#ifdef DEBUG
static bool
NewFunctionScopeIsWellFormed(ExclusiveContext* cx, HandleObject parent)
{
// Assert that the parent is null, global, or a debug scope proxy. All
// other cases of polluting global scope behavior are handled by
// ScopeObjects (viz. non-syntactic DynamicWithObject and
// NonSyntacticVariablesObject).
RootedObject realParent(cx, SkipScopeParent(parent));
return !realParent || realParent == cx->global() ||
realParent->is<DebugScopeObject>();
}
#endif
JSFunction*
js::NewFunctionWithProto(ExclusiveContext* cx, Native native,
unsigned nargs, JSFunction::Flags flags, HandleObject enclosingDynamicScope,
@ -2001,7 +2028,6 @@ js::NewFunctionWithProto(ExclusiveContext* cx, Native native,
{
MOZ_ASSERT(allocKind == AllocKind::FUNCTION || allocKind == AllocKind::FUNCTION_EXTENDED);
MOZ_ASSERT_IF(native, !enclosingDynamicScope);
MOZ_ASSERT(NewFunctionScopeIsWellFormed(cx, enclosingDynamicScope));
RootedObject funobj(cx);
// Don't mark asm.js module functions as singleton since they are
@ -2009,6 +2035,17 @@ js::NewFunctionWithProto(ExclusiveContext* cx, Native native,
// isSingleton implies isInterpreted.
if (native && !IsAsmJSModuleNative(native))
newKind = SingletonObject;
#ifdef DEBUG
RootedObject nonScopeParent(cx, SkipScopeParent(enclosingDynamicScope));
// We'd like to assert that nonScopeParent is null-or-global, but
// js::ExecuteInGlobalAndReturnScope and debugger eval bits mess that up.
// Assert that it's one of those or a debug scope proxy or the unqualified
// var obj, since it should still be ok to parent to the global in that
// case.
MOZ_ASSERT(!nonScopeParent || nonScopeParent == cx->global() ||
nonScopeParent->is<DebugScopeObject>() ||
nonScopeParent->isUnqualifiedVarObj());
#endif
funobj = NewObjectWithClassProto(cx, &JSFunction::class_, proto, allocKind,
newKind);
if (!funobj)
@ -2042,8 +2079,8 @@ js::NewFunctionWithProto(ExclusiveContext* cx, Native native,
}
bool
js::CanReuseScriptForClone(JSCompartment* compartment, HandleFunction fun,
HandleObject newParent)
js::CloneFunctionObjectUseSameScript(JSCompartment* compartment, HandleFunction fun,
HandleObject newParent)
{
if (compartment != fun->compartment() ||
fun->isSingleton() ||
@ -2064,36 +2101,75 @@ js::CanReuseScriptForClone(JSCompartment* compartment, HandleFunction fun,
return true;
// We need to clone the script if we're interpreted and not already marked
// as having a non-syntactic scope. If we're lazy, go ahead and clone the
// script; see the big comment at the end of CopyScriptInternal for the
// explanation of what's going on there.
// as having a polluted scope. If we're lazy, go ahead and clone the
// script; see the big comment at the end of CloneScript for the explanation
// of what's going on there.
return !fun->isInterpreted() ||
(fun->hasScript() && fun->nonLazyScript()->hasNonSyntacticScope());
(fun->hasScript() && fun->nonLazyScript()->hasPollutedGlobalScope());
}
static inline JSFunction*
NewFunctionClone(JSContext* cx, HandleFunction fun, NewObjectKind newKind,
gc::AllocKind allocKind, HandleObject proto)
JSFunction*
js::CloneFunctionObject(JSContext* cx, HandleFunction fun, HandleObject parent,
gc::AllocKind allocKind,
NewObjectKind newKindArg /* = GenericObject */,
HandleObject proto)
{
MOZ_ASSERT(parent);
MOZ_ASSERT(!fun->isBoundFunction());
bool useSameScript = CloneFunctionObjectUseSameScript(cx->compartment(), fun, parent);
NewObjectKind newKind = useSameScript ? newKindArg : SingletonObject;
RootedObject cloneProto(cx, proto);
if (!proto && fun->isStarGenerator()) {
if (!cloneProto && fun->isStarGenerator()) {
cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
if (!cloneProto)
return nullptr;
}
#ifdef DEBUG
RootedObject realParent(cx, SkipScopeParent(parent));
// We'd like to assert that realParent is null-or-global, but
// js::ExecuteInGlobalAndReturnScope and debugger eval bits mess that up.
// Assert that it's one of those or a debug scope proxy or the unqualified
// var obj, since it should still be ok to parent to the global in that
// case.
MOZ_ASSERT(!realParent || realParent == cx->global() ||
realParent->is<DebugScopeObject>() ||
realParent->isUnqualifiedVarObj());
#endif
JSObject* cloneobj = NewObjectWithClassProto(cx, &JSFunction::class_, cloneProto,
allocKind, newKind);
if (!cloneobj)
return nullptr;
RootedFunction clone(cx, &cloneobj->as<JSFunction>());
JSScript::AutoDelazify funScript(cx);
if (!useSameScript && fun->isInterpretedLazy()) {
funScript = fun;
if (!funScript)
return nullptr;
}
MOZ_ASSERT(useSameScript || !fun->isInterpretedLazy());
uint16_t flags = fun->flags() & ~JSFunction::EXTENDED;
if (allocKind == AllocKind::FUNCTION_EXTENDED)
flags |= JSFunction::EXTENDED;
clone->setArgCount(fun->nargs());
clone->setFlags(flags);
if (fun->hasScript()) {
clone->initScript(fun->nonLazyScript());
clone->initEnvironment(parent);
} else if (fun->isInterpretedLazy()) {
MOZ_ASSERT(fun->compartment() == clone->compartment());
MOZ_ASSERT(useSameScript);
LazyScript* lazy = fun->lazyScriptOrNull();
clone->initLazyScript(lazy);
clone->initEnvironment(parent);
} else {
clone->initNative(fun->native(), fun->jitInfo());
}
clone->initAtom(fun->displayAtom());
if (allocKind == AllocKind::FUNCTION_EXTENDED) {
@ -2105,103 +2181,34 @@ NewFunctionClone(JSContext* cx, HandleFunction fun, NewObjectKind newKind,
}
}
return clone;
}
JSFunction*
js::CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject parent,
gc::AllocKind allocKind /* = FUNCTION */ ,
NewObjectKind newKind /* = GenericObject */,
HandleObject proto /* = nullptr */)
{
MOZ_ASSERT(NewFunctionScopeIsWellFormed(cx, parent));
MOZ_ASSERT(!fun->isBoundFunction());
MOZ_ASSERT(CanReuseScriptForClone(cx->compartment(), fun, parent));
RootedFunction clone(cx, NewFunctionClone(cx, fun, newKind, allocKind, proto));
if (!clone)
return nullptr;
if (fun->hasScript()) {
clone->initScript(fun->nonLazyScript());
clone->initEnvironment(parent);
} else if (fun->isInterpretedLazy()) {
MOZ_ASSERT(fun->compartment() == clone->compartment());
LazyScript* lazy = fun->lazyScriptOrNull();
clone->initLazyScript(lazy);
clone->initEnvironment(parent);
} else {
clone->initNative(fun->native(), fun->jitInfo());
if (useSameScript) {
/*
* Clone the function, reusing its script. We can use the same group as
* the original function provided that its prototype is correct.
*/
if (fun->getProto() == clone->getProto())
clone->setGroup(fun->group());
return clone;
}
RootedFunction cloneRoot(cx, clone);
/*
* Clone the function, reusing its script. We can use the same group as
* the original function provided that its prototype is correct.
* Across compartments or if we have to introduce a polluted scope we have
* to clone the script for interpreted functions. Cross-compartment cloning
* only happens via JSAPI (JS::CloneFunctionObject) which dynamically
* ensures that 'script' has no enclosing lexical scope (only the global
* scope or other non-lexical scope).
*/
if (fun->getProto() == clone->getProto())
clone->setGroup(fun->group());
return clone;
}
JSFunction*
js::CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject parent,
HandleObject newStaticScope,
gc::AllocKind allocKind /* = FUNCTION */,
HandleObject proto /* = nullptr */)
{
MOZ_ASSERT(NewFunctionScopeIsWellFormed(cx, parent));
MOZ_ASSERT(!fun->isBoundFunction());
RootedFunction clone(cx, NewFunctionClone(cx, fun, SingletonObject, allocKind, proto));
if (!clone)
PollutedGlobalScopeOption globalScopeOption = parent->is<GlobalObject>() ?
HasCleanGlobalScope : HasPollutedGlobalScope;
if (cloneRoot->isInterpreted() &&
!CloneFunctionScript(cx, fun, cloneRoot, globalScopeOption, newKindArg))
{
return nullptr;
if (fun->hasScript()) {
clone->initScript(nullptr);
clone->initEnvironment(parent);
} else {
clone->initNative(fun->native(), fun->jitInfo());
}
/*
* Across compartments or if we have to introduce a non-syntactic scope we
* have to clone the script for interpreted functions. Cross-compartment
* cloning only happens via JSAPI (JS::CloneFunctionObject) which
* dynamically ensures that 'script' has no enclosing lexical scope (only
* the global scope or other non-lexical scope).
*/
#ifdef DEBUG
RootedObject terminatingScope(cx, parent);
while (IsSyntacticScope(terminatingScope))
terminatingScope = terminatingScope->enclosingScope();
MOZ_ASSERT_IF(!terminatingScope->is<GlobalObject>(),
HasNonSyntacticStaticScopeChain(newStaticScope));
#endif
if (clone->isInterpreted()) {
// The self-hosting compartment is shared across processes, and
// AutoDelazify enters fun->compartment(). We would get races if the
// self-hosting compartment has lazy interpreted functions.
MOZ_ASSERT_IF(fun->compartment()->isSelfHosting, !fun->isInterpretedLazy());
JSScript::AutoDelazify funScript(cx);
if (fun->isInterpretedLazy()) {
funScript = fun;
if (!funScript)
return nullptr;
}
RootedScript script(cx, fun->nonLazyScript());
MOZ_ASSERT(script->compartment() == fun->compartment());
MOZ_ASSERT(cx->compartment() == clone->compartment(),
"Otherwise we could relazify clone below!");
RootedScript clonedScript(cx, CloneScriptIntoFunction(cx, newStaticScope, clone, script));
if (!clonedScript)
return nullptr;
Debugger::onNewScript(cx, clonedScript);
}
return clone;
return cloneRoot;
}
/*

View File

@ -633,20 +633,14 @@ class FunctionExtended : public JSFunction
};
extern bool
CanReuseScriptForClone(JSCompartment* compartment, HandleFunction fun, HandleObject newParent);
CloneFunctionObjectUseSameScript(JSCompartment* compartment, HandleFunction fun,
HandleObject newParent);
extern JSFunction*
CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject parent,
gc::AllocKind kind = gc::AllocKind::FUNCTION,
NewObjectKind newKindArg = GenericObject,
HandleObject proto = nullptr);
// Functions whose scripts are cloned are always given singleton types.
extern JSFunction*
CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject parent,
HandleObject newStaticScope,
gc::AllocKind kind = gc::AllocKind::FUNCTION,
HandleObject proto = nullptr);
CloneFunctionObject(JSContext* cx, HandleFunction fun, HandleObject parent,
gc::AllocKind kind = gc::AllocKind::FUNCTION,
NewObjectKind newKindArg = GenericObject,
HandleObject proto = nullptr);
extern bool
FindBody(JSContext* cx, HandleFunction fun, HandleLinearString src, size_t* bodyStart,
@ -708,6 +702,10 @@ bool
XDRInterpretedFunction(XDRState<mode>* xdr, HandleObject enclosingScope,
HandleScript enclosingScript, MutableHandleFunction objp);
extern JSObject*
CloneFunctionAndScript(JSContext* cx, HandleObject enclosingScope, HandleFunction fun,
PollutedGlobalScopeOption polluted);
/*
* Report an error that call.thisv is not compatible with the specified class,
* assuming that the method (clasp->name).prototype.<name of callee function>

View File

@ -85,12 +85,7 @@ CloneFunctionObjectIfNotSingleton(JSContext* cx, HandleFunction fun, HandleObjec
gc::AllocKind kind = fun->isExtended()
? extendedFinalizeKind
: finalizeKind;
if (CanReuseScriptForClone(cx->compartment(), fun, parent))
return CloneFunctionReuseScript(cx, fun, parent, kind, newKind, proto);
RootedObject staticScope(cx, fun->getOrCreateScript(cx)->enclosingStaticScope());
return CloneFunctionAndScript(cx, fun, parent, staticScope, kind, proto);
return CloneFunctionObject(cx, fun, parent, kind, newKind, proto);
}
} /* namespace js */

View File

@ -1076,7 +1076,7 @@ NewObjectGCKind(const js::Class* clasp)
static inline JSObject*
NewObject(ExclusiveContext* cx, HandleObjectGroup group, gc::AllocKind kind,
NewObjectKind newKind, uint32_t initialShapeFlags = 0)
NewObjectKind newKind)
{
const Class* clasp = group->clasp();
@ -1091,8 +1091,7 @@ NewObject(ExclusiveContext* cx, HandleObjectGroup group, gc::AllocKind kind,
? GetGCKindSlots(gc::GetGCObjectKind(clasp), clasp)
: GetGCKindSlots(kind, clasp);
RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, group->proto(), nfixed,
initialShapeFlags));
RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, group->proto(), nfixed));
if (!shape)
return nullptr;
@ -1140,8 +1139,7 @@ NewObjectWithTaggedProtoIsCachable(ExclusiveContext* cxArg, Handle<TaggedProto>
JSObject*
js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
Handle<TaggedProto> proto,
gc::AllocKind allocKind, NewObjectKind newKind,
uint32_t initialShapeFlags)
gc::AllocKind allocKind, NewObjectKind newKind)
{
if (CanBeFinalizedInBackground(allocKind, clasp))
allocKind = GetBackgroundAllocKind(allocKind);
@ -1163,7 +1161,7 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
if (!group)
return nullptr;
RootedObject obj(cxArg, NewObject(cxArg, group, allocKind, newKind, initialShapeFlags));
RootedObject obj(cxArg, NewObject(cxArg, group, allocKind, newKind));
if (!obj)
return nullptr;

View File

@ -422,10 +422,10 @@ class JSObject : public js::gc::Cell
* slot of the object. For other scope objects, the chain goes directly to
* the global.
*
* In code which is not marked hasNonSyntacticScope, scope chains can
* In code which is not marked hasPollutedGlobalScope, scope chains can
* contain only syntactic scope objects (see IsSyntacticScope) with a global
* object at the root as the scope of the outermost non-function script. In
* hasNonSyntacticScope code, the scope of the outermost non-function
* hasPollutedGlobalScope code, the scope of the outermost non-function
* script might not be a global object, and can have a mix of other objects
* above it before the global object is reached.
*/

View File

@ -224,9 +224,6 @@ JSObject::isQualifiedVarObj()
{
if (is<js::DebugScopeObject>())
return as<js::DebugScopeObject>().scope().isQualifiedVarObj();
// TODO: We would like to assert that only GlobalObject or
// NonSyntacticVariables object is a qualified varobj, but users of
// js::Execute still need to be vetted. See bug 1171177.
return hasAllFlags(js::BaseShape::QUALIFIED_VAROBJ);
}
@ -235,9 +232,7 @@ JSObject::isUnqualifiedVarObj()
{
if (is<js::DebugScopeObject>())
return as<js::DebugScopeObject>().scope().isUnqualifiedVarObj();
bool rv = hasAllFlags(js::BaseShape::UNQUALIFIED_VAROBJ);
MOZ_ASSERT_IF(rv, is<js::GlobalObject>() || is<js::NonSyntacticVariablesObject>());
return rv;
return hasAllFlags(js::BaseShape::UNQUALIFIED_VAROBJ);
}
namespace js {
@ -608,38 +603,25 @@ typedef AutoVectorRooter<PropertyDescriptor> AutoPropertyDescriptorVector;
*/
JSObject*
NewObjectWithGivenTaggedProto(ExclusiveContext* cx, const Class* clasp, Handle<TaggedProto> proto,
gc::AllocKind allocKind, NewObjectKind newKind,
uint32_t initialShapeFlags = 0);
gc::AllocKind allocKind, NewObjectKind newKind);
inline JSObject*
NewObjectWithGivenTaggedProto(ExclusiveContext* cx, const Class* clasp, Handle<TaggedProto> proto,
NewObjectKind newKind = GenericObject,
uint32_t initialShapeFlags = 0)
NewObjectKind newKind = GenericObject)
{
gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
return NewObjectWithGivenTaggedProto(cx, clasp, proto, allocKind, newKind, initialShapeFlags);
return NewObjectWithGivenTaggedProto(cx, clasp, proto, allocKind, newKind);
}
template <typename T>
inline T*
NewObjectWithGivenTaggedProto(ExclusiveContext* cx, Handle<TaggedProto> proto,
NewObjectKind newKind = GenericObject,
uint32_t initialShapeFlags = 0)
NewObjectKind newKind = GenericObject)
{
JSObject* obj = NewObjectWithGivenTaggedProto(cx, &T::class_, proto, newKind,
initialShapeFlags);
JSObject* obj = NewObjectWithGivenTaggedProto(cx, &T::class_, proto, newKind);
return obj ? &obj->as<T>() : nullptr;
}
template <typename T>
inline T*
NewObjectWithNullTaggedProto(ExclusiveContext* cx, NewObjectKind newKind = GenericObject,
uint32_t initialShapeFlags = 0)
{
Rooted<TaggedProto> nullProto(cx, TaggedProto(nullptr));
return NewObjectWithGivenTaggedProto<T>(cx, nullProto, newKind, initialShapeFlags);
}
inline JSObject*
NewObjectWithGivenProto(ExclusiveContext* cx, const Class* clasp, HandleObject proto,
gc::AllocKind allocKind, NewObjectKind newKind)

View File

@ -576,10 +576,10 @@ enum XDRClassKind {
template<XDRMode mode>
bool
js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript enclosingScript,
js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
HandleFunction fun, MutableHandleScript scriptp)
{
/* NB: Keep this in sync with CopyScript. */
/* NB: Keep this in sync with CloneScript. */
enum ScriptBits {
NoScriptRval,
@ -600,7 +600,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
HasSingleton,
TreatAsRunOnce,
HasLazyScript,
HasNonSyntacticScope,
HasPollutedGlobalScope,
};
uint32_t length, lineno, column, nslots, staticLevel;
@ -613,7 +613,6 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
JSContext* cx = xdr->cx();
RootedScript script(cx);
RootedObject enclosingScope(cx, enclosingScopeArg);
natoms = nsrcnotes = 0;
nconsts = nobjects = nregexps = ntrynotes = nblockscopes = nyieldoffsets = 0;
@ -733,8 +732,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
scriptBits |= (1 << TreatAsRunOnce);
if (script->isRelazifiable())
scriptBits |= (1 << HasLazyScript);
if (script->hasNonSyntacticScope())
scriptBits |= (1 << HasNonSyntacticScope);
if (script->hasPollutedGlobalScope())
scriptBits |= (1 << HasPollutedGlobalScope);
}
if (!xdr->codeUint32(&prologueLength))
@ -802,26 +801,10 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
MOZ_ASSERT(enclosingScript->sourceObject()->is<ScriptSourceObject>());
sourceObject = &enclosingScript->sourceObject()->as<ScriptSourceObject>();
}
// If the outermost script has a non-syntactic scope, reflect that on
// the static scope chain.
if (scriptBits & (1 << HasNonSyntacticScope) && !enclosingScope) {
enclosingScope = StaticNonSyntacticScopeObjects::create(cx, nullptr);
if (!enclosingScope)
return false;
}
script = JSScript::Create(cx, enclosingScope, !!(scriptBits & (1 << SavedCallerFun)),
options, /* staticLevel = */ 0, sourceObject, 0, 0);
if (!script)
return false;
// Set the script in its function now so that inner scripts to be
// decoded may iterate the static scope chain.
if (fun) {
fun->initScript(script);
script->setFunction(fun);
}
}
/* JSScript::partiallyInit assumes script->bindings is fully initialized. */
@ -866,8 +849,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
script->hasSingletons_ = true;
if (scriptBits & (1 << TreatAsRunOnce))
script->treatAsRunOnce_ = true;
if (scriptBits & (1 << HasNonSyntacticScope))
script->hasNonSyntacticScope_ = true;
if (scriptBits & (1 << HasPollutedGlobalScope))
script->hasPollutedGlobalScope_ = true;
if (scriptBits & (1 << IsLegacyGenerator)) {
MOZ_ASSERT(!(scriptBits & (1 << IsStarGenerator)));
@ -999,12 +982,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
MOZ_ASSERT(enclosingStaticScopeIndex < i);
enclosingStaticScope = script->objects()->vector[enclosingStaticScopeIndex];
} else {
// This is not ternary because MSVC can't typecheck the
// ternary.
if (fun)
enclosingStaticScope = fun;
else
enclosingStaticScope = enclosingScope;
enclosingStaticScope = fun;
}
}
@ -1041,15 +1019,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
StaticScopeIter<NoGC> ssi(funEnclosingScope);
// Starting from a nested function, hitting a non-syntactic
// scope on the static scope chain means that its enclosing
// function has a non-syntactic scope. Nested functions
// themselves never have non-syntactic scope chains.
if (ssi.done() ||
ssi.type() == StaticScopeIter<NoGC>::NonSyntactic ||
ssi.type() == StaticScopeIter<NoGC>::Function)
{
MOZ_ASSERT_IF(ssi.done() || ssi.type() != StaticScopeIter<NoGC>::Function, !fun);
if (ssi.done() || ssi.type() == StaticScopeIter<NoGC>::Function) {
MOZ_ASSERT(ssi.done() == !fun);
funEnclosingScopeIndex = UINT32_MAX;
} else if (ssi.type() == StaticScopeIter<NoGC>::Block) {
funEnclosingScopeIndex = FindScopeObjectIndex(script, ssi.block());
@ -1065,12 +1036,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
if (mode == XDR_DECODE) {
if (funEnclosingScopeIndex == UINT32_MAX) {
// This is not ternary because MSVC can't typecheck the
// ternary.
if (fun)
funEnclosingScope = fun;
else
funEnclosingScope = enclosingScope;
funEnclosingScope = fun;
} else {
MOZ_ASSERT(funEnclosingScopeIndex < i);
funEnclosingScope = script->objects()->vector[funEnclosingScopeIndex];
@ -1211,13 +1177,9 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript
return false;
}
if (mode == XDR_DECODE) {
if (mode == XDR_DECODE)
lazy.set(LazyScript::Create(cx, fun, nullptr, enclosingScope, enclosingScript,
packedFields, begin, end, lineno, column));
if (!lazy)
return false;
fun->initLazyScript(lazy);
}
}
// Code free variables.
@ -2467,16 +2429,11 @@ JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCa
script->savedCallerFun_ = savedCallerFun;
script->initCompartment(cx);
script->hasPollutedGlobalScope_ = options.hasPollutedGlobalScope;
script->selfHosted_ = options.selfHostingMode;
script->noScriptRval_ = options.noScriptRval;
script->treatAsRunOnce_ = options.isRunOnce;
// Compute whether this script is under a non-syntactic scope. We don't
// need to walk the entire static scope chain if the script is nested in a
// function. In that case, we can propagate the cached value from the
// outer script.
script->hasNonSyntacticScope_ = HasNonSyntacticStaticScopeChain(enclosingScope);
script->version = options.version;
MOZ_ASSERT(script->getVersion() == options.version); // assert that no overflow occurred
@ -2712,13 +2669,10 @@ JSScript::fullyInitFromEmitter(ExclusiveContext* cx, HandleScript script, Byteco
RootedFunction fun(cx, nullptr);
if (funbox) {
// The function should have already been earlier to enable
// StaticScopeIter to walk the static scope chain of
// currently compiling scripts.
MOZ_ASSERT(script->functionNonDelazifying() == funbox->function());
MOZ_ASSERT(!bce->script->noScriptRval());
script->isGeneratorExp_ = funbox->inGenexpLambda;
script->setGeneratorKind(funbox->generatorKind());
script->setFunction(funbox->function());
if (bce->yieldOffsetList.length() != 0)
bce->yieldOffsetList.finish(script->yieldOffsets(), prologueLength);
}
@ -3051,48 +3005,15 @@ Rebase(JSScript* dst, JSScript* src, T* srcp)
return reinterpret_cast<T*>(dst->data + off);
}
static JSObject*
CloneInnerInterpretedFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction srcFun)
{
/* NB: Keep this in sync with XDRInterpretedFunction. */
RootedObject cloneProto(cx);
if (srcFun->isStarGenerator()) {
cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
if (!cloneProto)
return nullptr;
}
gc::AllocKind allocKind = srcFun->getAllocKind();
RootedFunction clone(cx, NewFunctionWithProto(cx, nullptr, 0,
JSFunction::INTERPRETED, nullptr, nullptr,
cloneProto, allocKind, TenuredObject));
if (!clone)
return nullptr;
JSScript::AutoDelazify srcScript(cx, srcFun);
if (!srcScript)
return nullptr;
JSScript* cloneScript = CloneScriptIntoFunction(cx, enclosingScope, clone, srcScript);
if (!cloneScript)
return nullptr;
clone->setArgCount(srcFun->nargs());
clone->setFlags(srcFun->flags());
clone->initAtom(srcFun->displayAtom());
if (!JSFunction::setTypeForScriptedFunction(cx, clone))
return nullptr;
return clone;
}
bool
js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src,
HandleScript dst)
JSScript*
js::CloneScript(JSContext* cx, HandleObject enclosingScope, HandleFunction fun, HandleScript src,
PollutedGlobalScopeOption polluted /* = HasCleanGlobalScope */,
NewObjectKind newKind /* = GenericObject */)
{
if (src->treatAsRunOnce() && !src->functionNonDelazifying()) {
// Toplevel run-once scripts may not be cloned.
JS_ReportError(cx, "No cloning toplevel run-once scripts");
return false;
return nullptr;
}
/* NB: Keep this in sync with XDRScript. */
@ -3105,14 +3026,13 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
uint32_t nregexps = src->hasRegexps() ? src->regexps()->length : 0;
uint32_t ntrynotes = src->hasTrynotes() ? src->trynotes()->length : 0;
uint32_t nblockscopes = src->hasBlockScopes() ? src->blockScopes()->length : 0;
uint32_t nyieldoffsets = src->hasYieldOffsets() ? src->yieldOffsets().length() : 0;
/* Script data */
size_t size = src->dataSize();
uint8_t* data = AllocScriptData(cx->zone(), size);
if (size && !data)
return false;
return nullptr;
/* Bindings */
@ -3120,7 +3040,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
InternalHandle<Bindings*> bindingsHandle =
InternalHandle<Bindings*>::fromMarkedLocation(bindings.address());
if (!Bindings::clone(cx, bindingsHandle, data, src))
return false;
return nullptr;
/* Objects */
@ -3137,7 +3057,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
if (NestedScopeObject* enclosingBlock = innerBlock->enclosingNestedScope())
enclosingScope = objects[FindScopeObjectIndex(src, *enclosingBlock)];
else
enclosingScope = scriptStaticScope;
enclosingScope = fun;
clone = CloneNestedScopeObject(cx, enclosingScope, innerBlock);
} else if (obj->is<JSFunction>()) {
@ -3146,36 +3066,32 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
if (cx->compartment() != innerFun->compartment()) {
MOZ_ASSERT(innerFun->isAsmJSNative());
JS_ReportError(cx, "AsmJS modules do not yet support cloning.");
return false;
return nullptr;
}
clone = innerFun;
} else {
if (innerFun->isInterpretedLazy()) {
AutoCompartment ac(cx, innerFun);
if (!innerFun->getOrCreateScript(cx))
return false;
return nullptr;
}
RootedObject staticScope(cx, innerFun->nonLazyScript()->enclosingStaticScope());
StaticScopeIter<CanGC> ssi(cx, staticScope);
RootedObject enclosingScope(cx);
if (ssi.done() || ssi.type() == StaticScopeIter<CanGC>::NonSyntactic) {
enclosingScope = scriptStaticScope;
} else if (ssi.type() == StaticScopeIter<CanGC>::Function) {
MOZ_ASSERT(scriptStaticScope->is<JSFunction>());
enclosingScope = scriptStaticScope;
} else if (ssi.type() == StaticScopeIter<CanGC>::Block) {
if (ssi.done() || ssi.type() == StaticScopeIter<CanGC>::Function)
enclosingScope = fun;
else if (ssi.type() == StaticScopeIter<CanGC>::Block)
enclosingScope = objects[FindScopeObjectIndex(src, ssi.block())];
} else {
else
enclosingScope = objects[FindScopeObjectIndex(src, ssi.staticWith())];
}
clone = CloneInnerInterpretedFunction(cx, enclosingScope, innerFun);
clone = CloneFunctionAndScript(cx, enclosingScope, innerFun, polluted);
}
} else {
clone = DeepCloneObjectLiteral(cx, obj, TenuredObject);
}
if (!clone || !objects.append(clone))
return false;
return nullptr;
}
}
@ -3187,11 +3103,50 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
for (unsigned i = 0; i < nregexps; i++) {
JSObject* clone = CloneScriptRegExpObject(cx, vector[i]->as<RegExpObject>());
if (!clone || !regexps.append(clone))
return false;
return nullptr;
}
}
/* Now that all fallible allocation is complete, do the copying. */
/*
* Wrap the script source object as needed. Self-hosted scripts may be
* in another runtime, so lazily create a new script source object to
* use for them.
*/
RootedObject sourceObject(cx);
if (cx->runtime()->isSelfHostingCompartment(src->compartment())) {
if (!cx->compartment()->selfHostingScriptSource) {
CompileOptions options(cx);
FillSelfHostingCompileOptions(options);
ScriptSourceObject* obj = frontend::CreateScriptSourceObject(cx, options);
if (!obj)
return nullptr;
cx->compartment()->selfHostingScriptSource.set(obj);
}
sourceObject = cx->compartment()->selfHostingScriptSource;
} else {
sourceObject = src->sourceObject();
if (!cx->compartment()->wrap(cx, &sourceObject))
return nullptr;
}
/* Now that all fallible allocation is complete, create the GC thing. */
CompileOptions options(cx);
options.setMutedErrors(src->mutedErrors())
.setHasPollutedScope(src->hasPollutedGlobalScope() ||
polluted == HasPollutedGlobalScope)
.setSelfHostingMode(src->selfHosted())
.setNoScriptRval(src->noScriptRval())
.setVersion(src->getVersion());
RootedScript dst(cx, JSScript::Create(cx, enclosingScope, src->savedCallerFun(),
options, src->staticLevel(),
sourceObject, src->sourceStart(), src->sourceEnd()));
if (!dst) {
js_free(data);
return nullptr;
}
dst->bindings = bindings;
@ -3250,112 +3205,64 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
dst->trynotes()->vector = Rebase<JSTryNote>(dst, src, src->trynotes()->vector);
if (nblockscopes != 0)
dst->blockScopes()->vector = Rebase<BlockScopeNote>(dst, src, src->blockScopes()->vector);
if (nyieldoffsets != 0)
dst->yieldOffsets().vector_ = Rebase<uint32_t>(dst, src, src->yieldOffsets().vector_);
/*
* Function delazification assumes that their script does not have a
* non-syntactic global scope. We ensure that as follows:
* polluted global scope. We ensure that as follows:
*
* 1) Initial parsing only creates lazy functions if
* !hasNonSyntacticScope.
* !hasPollutedGlobalScope.
* 2) Cloning a lazy function into a non-global scope will always require
* that its script be cloned. See comments in
* CloneFunctionObjectUseSameScript.
* 3) Cloning a script never sets a lazyScript on the clone, so the function
* cannot be relazified.
*
* If you decide that lazy functions should be supported with a
* non-syntactic global scope, make sure delazification can deal.
* If you decide that lazy functions should be supported with a polluted
* global scope, make sure delazification can deal.
*/
MOZ_ASSERT_IF(dst->hasNonSyntacticScope(), !dst->maybeLazyScript());
MOZ_ASSERT_IF(dst->hasNonSyntacticScope(), !dst->isRelazifiable());
MOZ_ASSERT_IF(dst->hasPollutedGlobalScope(), !dst->maybeLazyScript());
MOZ_ASSERT_IF(dst->hasPollutedGlobalScope(), !dst->isRelazifiable());
return dst;
}
bool
js::CloneFunctionScript(JSContext* cx, HandleFunction original, HandleFunction clone,
PollutedGlobalScopeOption polluted, NewObjectKind newKind)
{
RootedScript script(cx, clone->nonLazyScript());
MOZ_ASSERT(script);
MOZ_ASSERT(script->compartment() == original->compartment());
MOZ_ASSERT(cx->compartment() == clone->compartment(),
"Otherwise we could relazify clone below!");
// The only scripts with enclosing static scopes that may be cloned across
// compartments are non-strict, indirect eval scripts, as their dynamic
// scope chains terminate in the global scope immediately.
RootedObject scope(cx, script->enclosingStaticScope());
if (script->compartment() != cx->compartment() && scope) {
MOZ_ASSERT(!scope->as<StaticEvalObject>().isDirect() &&
!scope->as<StaticEvalObject>().isStrict());
scope = StaticEvalObject::create(cx, nullptr);
if (!scope)
return false;
}
clone->initScript(nullptr);
JSScript* cscript = CloneScript(cx, scope, clone, script, polluted, newKind);
if (!cscript)
return false;
clone->setScript(cscript);
cscript->setFunction(clone);
script = clone->nonLazyScript();
Debugger::onNewScript(cx, script);
return true;
}
static JSScript*
CreateEmptyScriptForClone(JSContext* cx, HandleObject enclosingScope, HandleScript src)
{
/*
* Wrap the script source object as needed. Self-hosted scripts may be
* in another runtime, so lazily create a new script source object to
* use for them.
*/
RootedObject sourceObject(cx);
if (cx->runtime()->isSelfHostingCompartment(src->compartment())) {
if (!cx->compartment()->selfHostingScriptSource) {
CompileOptions options(cx);
FillSelfHostingCompileOptions(options);
ScriptSourceObject* obj = frontend::CreateScriptSourceObject(cx, options);
if (!obj)
return nullptr;
cx->compartment()->selfHostingScriptSource.set(obj);
}
sourceObject = cx->compartment()->selfHostingScriptSource;
} else {
sourceObject = src->sourceObject();
if (!cx->compartment()->wrap(cx, &sourceObject))
return nullptr;
}
CompileOptions options(cx);
options.setMutedErrors(src->mutedErrors())
.setSelfHostingMode(src->selfHosted())
.setNoScriptRval(src->noScriptRval())
.setVersion(src->getVersion());
return JSScript::Create(cx, enclosingScope, src->savedCallerFun(),
options, src->staticLevel(),
sourceObject, src->sourceStart(), src->sourceEnd());
}
JSScript*
js::CloneGlobalScript(JSContext* cx, Handle<ScopeObject*> enclosingScope, HandleScript src)
{
// No enclosingScope means clean global.
MOZ_ASSERT(!enclosingScope || enclosingScope->is<StaticNonSyntacticScopeObjects>());
RootedScript dst(cx, CreateEmptyScriptForClone(cx, enclosingScope, src));
if (!dst)
return nullptr;
if (!detail::CopyScript(cx, enclosingScope, src, dst))
return nullptr;
return dst;
}
JSScript*
js::CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction fun,
HandleScript src)
{
MOZ_ASSERT(fun->isInterpreted());
// Allocate the destination script up front and set it as the script of
// |fun|, which is to be its container.
//
// This is so that when cloning nested functions, they can walk the static
// scope chain via fun and correctly compute the presence of a
// non-syntactic global.
RootedScript dst(cx, CreateEmptyScriptForClone(cx, enclosingScope, src));
if (!dst)
return nullptr;
dst->setFunction(fun);
if (fun->isInterpretedLazy())
fun->setUnlazifiedScript(dst);
else
fun->initScript(dst);
if (!detail::CopyScript(cx, fun, src, dst)) {
fun->setScript(nullptr);
return nullptr;
}
return dst;
}
DebugScript*
JSScript::debugScript()
{

View File

@ -55,15 +55,6 @@ namespace frontend {
class UpvarCookie;
}
namespace detail {
// Do not call this directly! It is exposed for the friend declarations in
// this file.
bool
CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src, HandleScript dst);
} // namespace detail
}
/*
@ -139,10 +130,6 @@ struct BlockScopeArray {
};
class YieldOffsetArray {
friend bool
detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src,
HandleScript dst);
uint32_t* vector_; // Array of bytecode offsets.
uint32_t length_; // Count of bytecode offsets.
@ -768,6 +755,16 @@ bool
XDRScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
HandleFunction fun, MutableHandleScript scriptp);
enum PollutedGlobalScopeOption {
HasPollutedGlobalScope,
HasCleanGlobalScope
};
JSScript*
CloneScript(JSContext* cx, HandleObject enclosingScope, HandleFunction fun, HandleScript script,
PollutedGlobalScopeOption polluted = HasCleanGlobalScope,
NewObjectKind newKind = GenericObject);
template<XDRMode mode>
bool
XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
@ -787,13 +784,13 @@ class JSScript : public js::gc::TenuredCell
template <js::XDRMode mode>
friend
bool
js::XDRScript(js::XDRState<mode>* xdr, js::HandleObject enclosingScope,
js::HandleScript enclosingScript,
js::XDRScript(js::XDRState<mode>* xdr, js::HandleObject enclosingScope, js::HandleScript enclosingScript,
js::HandleFunction fun, js::MutableHandleScript scriptp);
friend bool
js::detail::CopyScript(JSContext* cx, js::HandleObject scriptStaticScope, js::HandleScript src,
js::HandleScript dst);
friend JSScript*
js::CloneScript(JSContext* cx, js::HandleObject enclosingScope, js::HandleFunction fun,
js::HandleScript src, js::PollutedGlobalScopeOption polluted,
js::NewObjectKind newKind);
public:
//
@ -939,7 +936,7 @@ class JSScript : public js::gc::TenuredCell
// True if the script has a non-syntactic scope on its dynamic scope chain.
// That is, there are objects about which we know nothing between the
// outermost syntactic scope and the global.
bool hasNonSyntacticScope_:1;
bool hasPollutedGlobalScope_:1;
// see Parser::selfHostingMode.
bool selfHosted_:1;
@ -1181,8 +1178,8 @@ class JSScript : public js::gc::TenuredCell
bool explicitUseStrict() const { return explicitUseStrict_; }
bool hasNonSyntacticScope() const {
return hasNonSyntacticScope_;
bool hasPollutedGlobalScope() const {
return hasPollutedGlobalScope_;
}
bool selfHosted() const { return selfHosted_; }
@ -2296,12 +2293,9 @@ DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript maybeScr
uint32_t* pcOffset, bool* mutedErrors,
LineOption opt = NOT_CALLED_FROM_JSOP_EVAL);
JSScript*
CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction fun,
HandleScript src);
JSScript*
CloneGlobalScript(JSContext* cx, Handle<ScopeObject*> enclosingScope, HandleScript src);
bool
CloneFunctionScript(JSContext* cx, HandleFunction original, HandleFunction clone,
PollutedGlobalScopeOption polluted, NewObjectKind newKind);
} /* namespace js */

View File

@ -4318,36 +4318,6 @@ ReflectTrackedOptimizations(JSContext* cx, unsigned argc, Value* vp)
return true;
}
#ifdef DEBUG
static bool
DumpStaticScopeChain(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject callee(cx, &args.callee());
if (args.length() != 1) {
ReportUsageError(cx, callee, "Wrong number of arguments");
return false;
}
if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
ReportUsageError(cx, callee, "Argument must be an interpreted function");
return false;
}
RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
if (!fun->isInterpreted()) {
ReportUsageError(cx, callee, "Argument must be an interpreted function");
return false;
}
js::DumpStaticScopeChain(fun->getOrCreateScript(cx));
args.rval().setUndefined();
return true;
}
#endif
namespace js {
namespace shell {
@ -4996,12 +4966,6 @@ static const JSFunctionSpecWithHelp fuzzing_unsafe_functions[] = {
" any. If |fun| is not a scripted function or has not been compiled by\n"
" Ion, null is returned."),
#ifdef DEBUG
JS_FN_HELP("dumpStaticScopeChain", DumpStaticScopeChain, 1, 0,
"dumpStaticScopeChain(fun)",
" Prints the static scope chain of an interpreted function fun."),
#endif
JS_FS_HELP_END
};

View File

@ -6261,14 +6261,12 @@ EvaluateInEnv(JSContext* cx, Handle<Env*> env, HandleValue thisv, AbstractFrameP
* boundaries, and we are putting a DebugScopeProxy or non-syntactic With on
* the scope chain.
*/
Rooted<ScopeObject*> enclosingStaticScope(cx);
if (!env->is<GlobalObject>())
enclosingStaticScope = StaticNonSyntacticScopeObjects::create(cx, nullptr);
Rooted<StaticEvalObject*> staticScope(cx, StaticEvalObject::create(cx, enclosingStaticScope));
Rooted<StaticEvalObject*> staticScope(cx, StaticEvalObject::create(cx, nullptr));
if (!staticScope)
return false;
CompileOptions options(cx);
options.setIsRunOnce(true)
options.setHasPollutedScope(true)
.setIsRunOnce(true)
.setForEval(true)
.setNoScriptRval(false)
.setFileAndLine(filename, lineno)
@ -6277,8 +6275,8 @@ EvaluateInEnv(JSContext* cx, Handle<Env*> env, HandleValue thisv, AbstractFrameP
.maybeMakeStrictMode(frame ? frame.script()->strict() : false);
RootedScript callerScript(cx, frame ? frame.script() : nullptr);
SourceBufferHolder srcBuf(chars.start().get(), chars.length(), SourceBufferHolder::NoOwnership);
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(), env, staticScope,
callerScript, options, srcBuf,
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(), env, callerScript,
staticScope, options, srcBuf,
/* source = */ nullptr,
/* staticLevel = */ frame ? 1 : 0));
if (!script)
@ -6426,8 +6424,14 @@ DebuggerGenericEval(JSContext* cx, const char* fullMethodName, const Value& code
return false;
RootedObject dynamicScope(cx);
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, env, &dynamicScope))
// We ignore the static scope here. See comments about static
// scopes in EvaluateInEnv.
RootedObject unusedStaticScope(cx);
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, env, &dynamicScope,
&unusedStaticScope))
{
return false;
}
env = dynamicScope;
}

View File

@ -304,9 +304,9 @@ SetNameOperation(JSContext* cx, JSScript* script, jsbytecode* pc, HandleObject s
*pc == JSOP_STRICTSETNAME ||
*pc == JSOP_SETGNAME ||
*pc == JSOP_STRICTSETGNAME);
MOZ_ASSERT_IF(*pc == JSOP_SETGNAME && !script->hasNonSyntacticScope(),
MOZ_ASSERT_IF(*pc == JSOP_SETGNAME && !script->hasPollutedGlobalScope(),
scope == cx->global());
MOZ_ASSERT_IF(*pc == JSOP_STRICTSETGNAME && !script->hasNonSyntacticScope(),
MOZ_ASSERT_IF(*pc == JSOP_STRICTSETGNAME && !script->hasPollutedGlobalScope(),
scope == cx->global());
bool strict = *pc == JSOP_STRICTSETNAME || *pc == JSOP_STRICTSETGNAME;

View File

@ -274,7 +274,7 @@ GetNameOperation(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc, MutableHan
* the actual behavior even if the id could be found on the scope chain
* before the global object.
*/
if (IsGlobalOp(JSOp(*pc)) && !fp->script()->hasNonSyntacticScope())
if (IsGlobalOp(JSOp(*pc)) && !fp->script()->hasPollutedGlobalScope())
obj = &obj->global();
Shape* shape = nullptr;
@ -868,7 +868,7 @@ js::ExecuteKernel(JSContext* cx, HandleScript script, JSObject& scopeChainArg, c
while (IsSyntacticScope(terminatingScope))
terminatingScope = terminatingScope->enclosingScope();
MOZ_ASSERT(terminatingScope->is<GlobalObject>() ||
script->hasNonSyntacticScope());
script->hasPollutedGlobalScope());
#endif
if (script->treatAsRunOnce()) {
@ -904,8 +904,8 @@ js::Execute(JSContext* cx, HandleScript script, JSObject& scopeChainArg, Value*
RootedObject scopeChain(cx, &scopeChainArg);
MOZ_ASSERT(scopeChain == GetInnerObject(scopeChain));
MOZ_RELEASE_ASSERT(scopeChain->is<GlobalObject>() || script->hasNonSyntacticScope(),
"Only scripts with non-syntactic scopes can be executed with "
MOZ_RELEASE_ASSERT(scopeChain->is<GlobalObject>() || script->hasPollutedGlobalScope(),
"Only scripts with polluted scopes can be executed with "
"interesting scopechains");
/* Ensure the scope chain is all same-compartment and terminates in a global. */
@ -1182,7 +1182,6 @@ PopScope(JSContext* cx, ScopeIter& si)
break;
case ScopeIter::Call:
case ScopeIter::Eval:
case ScopeIter::NonSyntactic:
break;
}
}
@ -2321,7 +2320,7 @@ CASE(JSOP_BINDGNAME)
CASE(JSOP_BINDNAME)
{
JSOp op = JSOp(*REGS.pc);
if (op == JSOP_BINDNAME || script->hasNonSyntacticScope()) {
if (op == JSOP_BINDNAME || script->hasPollutedGlobalScope()) {
ReservedRooted<JSObject*> scopeChain(&rootObject0, REGS.fp()->scopeChain());
ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
@ -3063,7 +3062,7 @@ CASE(JSOP_IMPLICITTHIS)
CASE(JSOP_GIMPLICITTHIS)
{
JSOp op = JSOp(*REGS.pc);
if (op == JSOP_IMPLICITTHIS || script->hasNonSyntacticScope()) {
if (op == JSOP_IMPLICITTHIS || script->hasPollutedGlobalScope()) {
ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
ReservedRooted<JSObject*> scopeObj(&rootObject0, REGS.fp()->scopeChain());
ReservedRooted<JSObject*> scope(&rootObject1);
@ -3942,7 +3941,7 @@ CASE(JSOP_SUPERBASE)
{
ScopeIter si(cx, REGS.fp()->scopeChain(), REGS.fp()->script()->innermostStaticScope(REGS.pc));
for (; !si.done(); ++si) {
if (si.hasSyntacticScopeObject() && si.type() == ScopeIter::Call) {
if (si.hasScopeObject() && si.type() == ScopeIter::Call) {
JSFunction& callee = si.scope().as<CallObject>().callee();
// Arrow functions don't have the information we're looking for,

View File

@ -1570,9 +1570,9 @@
macro(JSOP_RETRVAL, 153,"retrval", NULL, 1, 0, 0, JOF_BYTE) \
\
/*
* Looks up name on global scope and pushes its value onto the stack,
* unless the script has a non-syntactic global scope, in which case it
* acts just like JSOP_NAME.
* Looks up name on global scope and pushes its value onto the stack, unless
* the script has a polluted global, in which case it acts just like
* JSOP_NAME.
*
* Free variable references that must either be found on the global or a
* ReferenceError.
@ -1586,7 +1586,7 @@
* Pops the top two values on the stack as 'val' and 'scope', sets property
* of 'scope' as 'val' and pushes 'val' back on the stack.
*
* 'scope' should be the global scope unless the script has a non-syntactic
* 'scope' should be the global scope unless the script has a polluted
* global scope, in which case acts like JSOP_SETNAME.
* Category: Variables and Scopes
* Type: Free Variables
@ -1600,7 +1600,7 @@
* of 'scope' as 'val' and pushes 'val' back on the stack. Throws a
* TypeError if the set fails, per strict mode semantics.
*
* 'scope' should be the global scope unless the script has a non-syntactic
* 'scope' should be the global scope unless the script has a polluted
* global scope, in which case acts like JSOP_STRICTSETNAME.
* Category: Variables and Scopes
* Type: Free Variables
@ -1871,7 +1871,7 @@
macro(JSOP_UNUSED213, 213, "unused213", NULL, 1, 0, 0, JOF_BYTE) \
/*
* Pushes the global scope onto the stack if the script doesn't have a
* non-syntactic global scope. Otherwise will act like JSOP_BINDNAME.
* polluted global scope. Otherwise will act like JSOP_BINDNAME.
*
* 'nameIndex' is only used when acting like JSOP_BINDNAME.
* Category: Variables and Scopes

View File

@ -84,8 +84,6 @@ StaticScopeIter<allowGC>::operator++(int)
obj = obj->template as<NestedScopeObject>().enclosingScopeForStaticScopeIter();
} else if (obj->template is<StaticEvalObject>()) {
obj = obj->template as<StaticEvalObject>().enclosingScopeForStaticScopeIter();
} else if (obj->template is<StaticNonSyntacticScopeObjects>()) {
obj = obj->template as<StaticNonSyntacticScopeObjects>().enclosingScopeForStaticScopeIter();
} else if (onNamedLambda || !obj->template as<JSFunction>().isNamedLambda()) {
onNamedLambda = false;
obj = obj->template as<JSFunction>().nonLazyScript()->enclosingStaticScope();
@ -94,32 +92,27 @@ StaticScopeIter<allowGC>::operator++(int)
}
MOZ_ASSERT_IF(obj, obj->template is<NestedScopeObject>() ||
obj->template is<StaticEvalObject>() ||
obj->template is<StaticNonSyntacticScopeObjects>() ||
obj->template is<JSFunction>());
MOZ_ASSERT_IF(onNamedLambda, obj->template is<JSFunction>());
}
template <AllowGC allowGC>
inline bool
StaticScopeIter<allowGC>::hasSyntacticDynamicScopeObject() const
StaticScopeIter<allowGC>::hasDynamicScopeObject() const
{
if (obj->template is<JSFunction>())
return obj->template as<JSFunction>().isHeavyweight();
if (obj->template is<StaticBlockObject>())
return obj->template as<StaticBlockObject>().needsClone();
if (obj->template is<StaticWithObject>())
return true;
if (obj->template is<StaticEvalObject>())
return obj->template as<StaticEvalObject>().isStrict();
MOZ_ASSERT(obj->template is<StaticNonSyntacticScopeObjects>());
return false;
return obj->template is<StaticBlockObject>()
? obj->template as<StaticBlockObject>().needsClone()
: (obj->template is<StaticEvalObject>()
? obj->template as<StaticEvalObject>().isStrict()
: (obj->template is<StaticWithObject>() ||
obj->template as<JSFunction>().isHeavyweight()));
}
template <AllowGC allowGC>
inline Shape*
StaticScopeIter<allowGC>::scopeShape() const
{
MOZ_ASSERT(hasSyntacticDynamicScopeObject());
MOZ_ASSERT(hasDynamicScopeObject());
MOZ_ASSERT(type() != NamedLambda && type() != Eval);
if (type() == Block)
return block().lastProperty();
@ -138,8 +131,6 @@ StaticScopeIter<allowGC>::type() const
? With
: (obj->template is<StaticEvalObject>()
? Eval
: (obj->template is<StaticNonSyntacticScopeObjects>())
? NonSyntactic
: Function));
}
@ -167,14 +158,6 @@ StaticScopeIter<allowGC>::eval() const
return obj->template as<StaticEvalObject>();
}
template <AllowGC allowGC>
inline StaticNonSyntacticScopeObjects&
StaticScopeIter<allowGC>::nonSyntactic() const
{
MOZ_ASSERT(type() == NonSyntactic);
return obj->template as<StaticNonSyntacticScopeObjects>();
}
template <AllowGC allowGC>
inline JSScript*
StaticScopeIter<allowGC>::funScript() const

View File

@ -43,7 +43,7 @@ js::ScopeCoordinateToStaticScopeShape(JSScript* script, jsbytecode* pc)
uint32_t hops = ScopeCoordinate(pc).hops();
while (true) {
MOZ_ASSERT(!ssi.done());
if (ssi.hasSyntacticDynamicScopeObject()) {
if (ssi.hasDynamicScopeObject()) {
if (!hops)
break;
hops--;
@ -107,7 +107,7 @@ js::ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc)
StaticScopeIter<NoGC> ssi(script->innermostStaticScopeInScript(pc));
uint32_t hops = ScopeCoordinate(pc).hops();
while (true) {
if (ssi.hasSyntacticDynamicScopeObject()) {
if (ssi.hasDynamicScopeObject()) {
if (!hops)
break;
hops--;
@ -212,7 +212,7 @@ CallObject::create(JSContext* cx, HandleScript script, HandleObject enclosing, H
if (!callobj)
return nullptr;
callobj->setEnclosingScope(enclosing);
callobj->as<ScopeObject>().setEnclosingScope(enclosing);
callobj->initFixedSlot(CALLEE_SLOT, ObjectOrNullValue(callee));
if (script->treatAsRunOnce()) {
@ -323,10 +323,22 @@ const Class DeclEnvObject::class_ = {
* scope and callee) or used as a template for jit compilation.
*/
DeclEnvObject*
DeclEnvObject::createTemplateObject(JSContext* cx, HandleFunction fun, NewObjectKind newKind)
DeclEnvObject::createTemplateObject(JSContext* cx, HandleFunction fun, gc::InitialHeap heap)
{
Rooted<DeclEnvObject*> obj(cx);
obj = NewObjectWithNullTaggedProto<DeclEnvObject>(cx, newKind, BaseShape::DELEGATE);
MOZ_ASSERT(IsNurseryAllocable(FINALIZE_KIND));
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
if (!group)
return nullptr;
RootedShape emptyDeclEnvShape(cx);
emptyDeclEnvShape = EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
FINALIZE_KIND, BaseShape::DELEGATE);
if (!emptyDeclEnvShape)
return nullptr;
RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND, heap,
emptyDeclEnvShape, group)));
if (!obj)
return nullptr;
@ -344,13 +356,13 @@ DeclEnvObject::createTemplateObject(JSContext* cx, HandleFunction fun, NewObject
return nullptr;
MOZ_ASSERT(!obj->hasDynamicSlots());
return obj;
return &obj->as<DeclEnvObject>();
}
DeclEnvObject*
DeclEnvObject::create(JSContext* cx, HandleObject enclosing, HandleFunction callee)
{
Rooted<DeclEnvObject*> obj(cx, createTemplateObject(cx, callee, GenericObject));
Rooted<DeclEnvObject*> obj(cx, createTemplateObject(cx, callee, gc::DefaultHeap));
if (!obj)
return nullptr;
@ -388,7 +400,20 @@ js::XDRStaticWithObject(XDRState<XDR_DECODE>*, HandleObject, MutableHandle<Stati
StaticWithObject*
StaticWithObject::create(ExclusiveContext* cx)
{
return NewObjectWithNullTaggedProto<StaticWithObject>(cx, TenuredObject, BaseShape::DELEGATE);
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
if (!group)
return nullptr;
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
FINALIZE_KIND));
if (!shape)
return nullptr;
RootedObject obj(cx, JSObject::create(cx, FINALIZE_KIND, gc::TenuredHeap, shape, group));
if (!obj)
return nullptr;
return &obj->as<StaticWithObject>();
}
static JSObject*
@ -408,11 +433,18 @@ DynamicWithObject::create(JSContext* cx, HandleObject object, HandleObject enclo
HandleObject staticWith, WithKind kind)
{
MOZ_ASSERT(staticWith->is<StaticWithObject>());
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_,
TaggedProto(staticWith.get())));
if (!group)
return nullptr;
Rooted<TaggedProto> proto(cx, TaggedProto(staticWith));
Rooted<DynamicWithObject*> obj(cx);
obj = NewObjectWithGivenTaggedProto<DynamicWithObject>(cx, proto, GenericObject,
BaseShape::DELEGATE);
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(staticWith),
FINALIZE_KIND));
if (!shape)
return nullptr;
RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND,
gc::DefaultHeap, shape, group)));
if (!obj)
return nullptr;
@ -420,12 +452,12 @@ DynamicWithObject::create(JSContext* cx, HandleObject object, HandleObject enclo
if (!thisp)
return nullptr;
obj->setEnclosingScope(enclosing);
obj->as<ScopeObject>().setEnclosingScope(enclosing);
obj->setFixedSlot(OBJECT_SLOT, ObjectValue(*object));
obj->setFixedSlot(THIS_SLOT, ObjectValue(*thisp));
obj->setFixedSlot(KIND_SLOT, Int32Value(kind));
return obj;
return &obj->as<DynamicWithObject>();
}
static bool
@ -535,14 +567,23 @@ const Class DynamicWithObject::class_ = {
/* static */ StaticEvalObject*
StaticEvalObject::create(JSContext* cx, HandleObject enclosing)
{
StaticEvalObject* obj =
NewObjectWithNullTaggedProto<StaticEvalObject>(cx, TenuredObject, BaseShape::DELEGATE);
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
if (!group)
return nullptr;
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
FINALIZE_KIND, BaseShape::DELEGATE));
if (!shape)
return nullptr;
RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND,
gc::TenuredHeap, shape, group)));
if (!obj)
return nullptr;
obj->setReservedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(enclosing));
obj->setReservedSlot(STRICT_SLOT, BooleanValue(false));
return obj;
return &obj->as<StaticEvalObject>();
}
const Class StaticEvalObject::class_ = {
@ -551,50 +592,6 @@ const Class StaticEvalObject::class_ = {
JSCLASS_IS_ANONYMOUS
};
/* static */ StaticNonSyntacticScopeObjects*
StaticNonSyntacticScopeObjects::create(JSContext*cx, HandleObject enclosing)
{
StaticNonSyntacticScopeObjects* obj =
NewObjectWithNullTaggedProto<StaticNonSyntacticScopeObjects>(cx, TenuredObject,
BaseShape::DELEGATE);
if (!obj)
return nullptr;
obj->setReservedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(enclosing));
return obj;
}
const Class StaticNonSyntacticScopeObjects::class_ = {
"StaticNonSyntacticScopeObjects",
JSCLASS_HAS_RESERVED_SLOTS(StaticNonSyntacticScopeObjects::RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS
};
/* static */ NonSyntacticVariablesObject*
NonSyntacticVariablesObject::create(JSContext* cx, Handle<GlobalObject*> global)
{
Rooted<NonSyntacticVariablesObject*> obj(cx,
NewObjectWithNullTaggedProto<NonSyntacticVariablesObject>(cx, TenuredObject,
BaseShape::DELEGATE));
if (!obj)
return nullptr;
if (!obj->setQualifiedVarObj(cx))
return nullptr;
if (!obj->setUnqualifiedVarObj(cx))
return nullptr;
obj->setEnclosingScope(global);
return obj;
}
const Class NonSyntacticVariablesObject::class_ = {
"NonSyntacticVariablesObject",
JSCLASS_HAS_RESERVED_SLOTS(NonSyntacticVariablesObject::RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS
};
/*****************************************************************************/
/* static */ ClonedBlockObject*
@ -609,10 +606,7 @@ ClonedBlockObject::create(JSContext* cx, Handle<StaticBlockObject*> block, Handl
RootedShape shape(cx, block->lastProperty());
gc::AllocKind allocKind = gc::GetGCObjectKind(&BlockObject::class_);
if (CanBeFinalizedInBackground(allocKind, &BlockObject::class_))
allocKind = GetBackgroundAllocKind(allocKind);
RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, allocKind,
RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND,
gc::TenuredHeap, shape, group)));
if (!obj)
return nullptr;
@ -686,7 +680,22 @@ ClonedBlockObject::clone(JSContext* cx, Handle<ClonedBlockObject*> clonedBlock)
StaticBlockObject*
StaticBlockObject::create(ExclusiveContext* cx)
{
return NewObjectWithNullTaggedProto<StaticBlockObject>(cx, TenuredObject, BaseShape::DELEGATE);
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &BlockObject::class_,
TaggedProto(nullptr)));
if (!group)
return nullptr;
RootedShape emptyBlockShape(cx);
emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockObject::class_, TaggedProto(nullptr),
FINALIZE_KIND, BaseShape::DELEGATE);
if (!emptyBlockShape)
return nullptr;
JSObject* obj = JSObject::create(cx, FINALIZE_KIND, gc::TenuredHeap, emptyBlockShape, group);
if (!obj)
return nullptr;
return &obj->as<StaticBlockObject>();
}
/* static */ Shape*
@ -884,13 +893,22 @@ js::CloneNestedScopeObject(JSContext* cx, HandleObject enclosingScope, Handle<Ne
/* static */ UninitializedLexicalObject*
UninitializedLexicalObject::create(JSContext* cx, HandleObject enclosing)
{
UninitializedLexicalObject* obj =
NewObjectWithNullTaggedProto<UninitializedLexicalObject>(cx, GenericObject,
BaseShape::DELEGATE);
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
if (!group)
return nullptr;
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
FINALIZE_KIND));
if (!shape)
return nullptr;
RootedObject obj(cx, JSObject::create(cx, FINALIZE_KIND, gc::DefaultHeap, shape, group));
if (!obj)
return nullptr;
obj->setEnclosingScope(enclosing);
return obj;
obj->as<ScopeObject>().setEnclosingScope(enclosing);
return &obj->as<UninitializedLexicalObject>();
}
static void
@ -1027,14 +1045,7 @@ ScopeIter::ScopeIter(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc
void
ScopeIter::incrementStaticScopeIter()
{
// If settled on a non-syntactic static scope, only increment ssi_ once
// we've iterated through all the non-syntactic dynamic ScopeObjects.
if (ssi_.type() == StaticScopeIter<CanGC>::NonSyntactic) {
if (!hasNonSyntacticScopeObject())
ssi_++;
} else {
ssi_++;
}
ssi_++;
// For named lambdas, DeclEnvObject scopes are always attached to their
// CallObjects. Skip it here, as they are special cased in users of
@ -1061,7 +1072,7 @@ ScopeIter::settle()
frame_ = NullFramePtr();
#ifdef DEBUG
if (!ssi_.done() && hasAnyScopeObject()) {
if (!ssi_.done() && hasScopeObject()) {
switch (ssi_.type()) {
case StaticScopeIter<CanGC>::Function:
MOZ_ASSERT(scope_->as<CallObject>().callee().nonLazyScript() == ssi_.funScript());
@ -1075,9 +1086,6 @@ ScopeIter::settle()
case StaticScopeIter<CanGC>::Eval:
MOZ_ASSERT(scope_->as<CallObject>().isForEval());
break;
case StaticScopeIter<CanGC>::NonSyntactic:
MOZ_ASSERT(!IsSyntacticScope(scope_));
break;
case StaticScopeIter<CanGC>::NamedLambda:
MOZ_CRASH("named lambda static scopes should have been skipped");
}
@ -1088,7 +1096,7 @@ ScopeIter::settle()
ScopeIter&
ScopeIter::operator++()
{
if (hasAnyScopeObject()) {
if (hasScopeObject()) {
scope_ = &scope_->as<ScopeObject>().enclosingScope();
if (scope_->is<DeclEnvObject>())
scope_ = &scope_->as<DeclEnvObject>().enclosingScope();
@ -1114,8 +1122,6 @@ ScopeIter::type() const
return With;
case StaticScopeIter<CanGC>::Eval:
return Eval;
case StaticScopeIter<CanGC>::NonSyntactic:
return NonSyntactic;
case StaticScopeIter<CanGC>::NamedLambda:
MOZ_CRASH("named lambda static scopes should have been skipped");
default:
@ -1126,7 +1132,7 @@ ScopeIter::type() const
ScopeObject&
ScopeIter::scope() const
{
MOZ_ASSERT(hasAnyScopeObject());
MOZ_ASSERT(hasScopeObject());
return scope_->as<ScopeObject>();
}
@ -1145,8 +1151,6 @@ ScopeIter::maybeStaticScope() const
return &staticWith();
case StaticScopeIter<CanGC>::Eval:
return &staticEval();
case StaticScopeIter<CanGC>::NonSyntactic:
return &staticNonSyntactic();
case StaticScopeIter<CanGC>::NamedLambda:
MOZ_CRASH("named lambda static scopes should have been skipped");
default:
@ -1746,7 +1750,7 @@ const DebugScopeProxy DebugScopeProxy::singleton;
DebugScopeObject::create(JSContext* cx, ScopeObject& scope, HandleObject enclosing)
{
MOZ_ASSERT(scope.compartment() == cx->compartment());
MOZ_ASSERT(!enclosing->is<ScopeObject>());
MOZ_ASSERT(!IsSyntacticScope(enclosing));
RootedValue priv(cx, ObjectValue(scope));
JSObject* obj = NewProxyObject(cx, &DebugScopeProxy::singleton, priv,
@ -2008,7 +2012,7 @@ DebugScopes::addDebugScope(JSContext* cx, ScopeObject& scope, DebugScopeObject&
DebugScopeObject*
DebugScopes::hasDebugScope(JSContext* cx, const ScopeIter& si)
{
MOZ_ASSERT(!si.hasSyntacticScopeObject());
MOZ_ASSERT(!si.hasScopeObject());
DebugScopes* scopes = cx->compartment()->debugScopes;
if (!scopes)
@ -2024,7 +2028,7 @@ DebugScopes::hasDebugScope(JSContext* cx, const ScopeIter& si)
bool
DebugScopes::addDebugScope(JSContext* cx, const ScopeIter& si, DebugScopeObject& debugScope)
{
MOZ_ASSERT(!si.hasSyntacticScopeObject());
MOZ_ASSERT(!si.hasScopeObject());
MOZ_ASSERT(cx->compartment() == debugScope.compartment());
MOZ_ASSERT_IF(si.withinInitialFrame() && si.initialFrame().isFunctionFrame(),
!si.initialFrame().callee()->isGenerator());
@ -2242,7 +2246,7 @@ DebugScopes::updateLiveScopes(JSContext* cx)
continue;
for (ScopeIter si(cx, frame, i.pc()); si.withinInitialFrame(); ++si) {
if (si.hasSyntacticScopeObject()) {
if (si.hasScopeObject()) {
MOZ_ASSERT(si.scope().compartment() == cx->compartment());
DebugScopes* scopes = ensureCompartmentData(cx);
if (!scopes)
@ -2360,7 +2364,7 @@ GetDebugScopeForScope(JSContext* cx, const ScopeIter& si)
static DebugScopeObject*
GetDebugScopeForMissing(JSContext* cx, const ScopeIter& si)
{
MOZ_ASSERT(!si.hasSyntacticScopeObject() && si.canHaveSyntacticScopeObject());
MOZ_ASSERT(!si.hasScopeObject() && si.canHaveScopeObject());
if (DebugScopeObject* debugScope = DebugScopes::hasDebugScope(cx, si))
return debugScope;
@ -2427,8 +2431,6 @@ GetDebugScopeForMissing(JSContext* cx, const ScopeIter& si)
case ScopeIter::With:
case ScopeIter::Eval:
MOZ_CRASH("should already have a scope");
case ScopeIter::NonSyntactic:
MOZ_CRASH("non-syntactic scopes cannot be synthesized");
}
if (!debugScope)
return nullptr;
@ -2443,11 +2445,11 @@ static JSObject*
GetDebugScopeForNonScopeObject(const ScopeIter& si)
{
JSObject& enclosing = si.enclosingScope();
MOZ_ASSERT(!enclosing.is<ScopeObject>());
MOZ_ASSERT(!IsSyntacticScope(&enclosing));
#ifdef DEBUG
JSObject* o = &enclosing;
while ((o = o->enclosingScope()))
MOZ_ASSERT(!o->is<ScopeObject>());
MOZ_ASSERT(!IsSyntacticScope(o));
#endif
return &enclosing;
}
@ -2460,10 +2462,10 @@ GetDebugScope(JSContext* cx, const ScopeIter& si)
if (si.done())
return GetDebugScopeForNonScopeObject(si);
if (si.hasAnyScopeObject())
if (si.hasScopeObject())
return GetDebugScopeForScope(cx, si);
if (si.canHaveSyntacticScopeObject())
if (si.canHaveScopeObject())
return GetDebugScopeForMissing(cx, si);
ScopeIter copy(cx, si);
@ -2512,7 +2514,8 @@ js::GetObjectEnvironmentObjectForFunction(JSFunction* fun)
bool
js::CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
HandleObject dynamicTerminatingScope,
MutableHandleObject dynamicScopeObj)
MutableHandleObject dynamicScopeObj,
MutableHandleObject staticScopeObj)
{
#ifdef DEBUG
for (size_t i = 0; i < scopeChain.length(); ++i) {
@ -2542,55 +2545,12 @@ js::CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
}
dynamicScopeObj.set(dynamicEnclosingScope);
staticScopeObj.set(staticEnclosingScope);
return true;
}
bool
js::HasNonSyntacticStaticScopeChain(JSObject* staticScope)
{
for (StaticScopeIter<NoGC> ssi(staticScope); !ssi.done(); ssi++) {
// If we hit a function scope, we can short circuit the logic, as
// scripts cache whether they are under a non-syntactic scope.
if (ssi.type() == StaticScopeIter<NoGC>::Function)
return ssi.funScript()->hasNonSyntacticScope();
if (ssi.type() == StaticScopeIter<NoGC>::NonSyntactic)
return true;
}
return false;
}
#ifdef DEBUG
void
js::DumpStaticScopeChain(JSScript* script)
{
JSObject* enclosingScope = script->enclosingStaticScope();
for (StaticScopeIter<NoGC> ssi(enclosingScope); !ssi.done(); ssi++) {
switch (ssi.type()) {
case StaticScopeIter<NoGC>::Function:
fprintf(stdout, "function");
break;
case StaticScopeIter<NoGC>::Block:
fprintf(stdout, "block");
break;
case StaticScopeIter<NoGC>::With:
fprintf(stdout, "with");
break;
case StaticScopeIter<NoGC>::NamedLambda:
fprintf(stdout, "named lambda");
break;
case StaticScopeIter<NoGC>::Eval:
fprintf(stdout, "eval");
break;
case StaticScopeIter<NoGC>::NonSyntactic:
fprintf(stdout, "non-syntactic");
break;
}
fprintf(stdout, " -> ");
}
fprintf(stdout, "global\n");
}
typedef HashSet<PropertyName*> PropertyNameSet;
static bool
@ -2623,7 +2583,7 @@ RemoveReferencedNames(JSContext* cx, HandleScript script, PropertyNameSet& remai
case JSOP_GETGNAME:
case JSOP_SETGNAME:
case JSOP_STRICTSETGNAME:
if (script->hasNonSyntacticScope())
if (script->hasPollutedGlobalScope())
name = script->getName(pc);
else
name = nullptr;

View File

@ -22,7 +22,6 @@ namespace frontend { struct Definition; }
class StaticWithObject;
class StaticEvalObject;
class StaticNonSyntacticScopeObjects;
/*****************************************************************************/
@ -63,7 +62,6 @@ class StaticScopeIter
obj->is<StaticBlockObject>() ||
obj->is<StaticWithObject>() ||
obj->is<StaticEvalObject>() ||
obj->is<StaticNonSyntacticScopeObjects>() ||
obj->is<JSFunction>());
}
@ -83,7 +81,6 @@ class StaticScopeIter
obj->is<StaticBlockObject>() ||
obj->is<StaticWithObject>() ||
obj->is<StaticEvalObject>() ||
obj->is<StaticNonSyntacticScopeObjects>() ||
obj->is<JSFunction>());
}
@ -98,19 +95,16 @@ class StaticScopeIter
bool done() const;
void operator++(int);
// Return whether this static scope will have a syntactic scope (i.e. a
// ScopeObject that isn't a non-syntactic With or
// NonSyntacticVariablesObject) on the dynamic scope chain.
bool hasSyntacticDynamicScopeObject() const;
/* Return whether this static scope will be on the dynamic scope chain. */
bool hasDynamicScopeObject() const;
Shape* scopeShape() const;
enum Type { Function, Block, With, NamedLambda, Eval, NonSyntactic };
enum Type { Function, Block, With, NamedLambda, Eval };
Type type() const;
StaticBlockObject& block() const;
StaticWithObject& staticWith() const;
StaticEvalObject& eval() const;
StaticNonSyntacticScopeObjects& nonSyntactic() const;
JSScript* funScript() const;
JSFunction& fun() const;
};
@ -181,28 +175,26 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
* scope objects is:
*
* JSObject Generic object
* |
* ScopeObject---+---+ Engine-internal scope
* | | | | |
* | | | | StaticNonSyntacticScopeObjects See NB2
* | | | |
* | | | StaticEvalObject Placeholder so eval scopes may be iterated through
* | | |
* | | DeclEnvObject Holds name of recursive/heavyweight named lambda
* | |
* | CallObject Scope of entire function or strict eval
* |
* NestedScopeObject Scope created for a statement
* | | |
* | | StaticWithObject Template for "with" object in static scope chain
* | |
* | DynamicWithObject Run-time "with" object on scope chain
* |
* BlockObject Shared interface of cloned/static block objects
* | |
* | ClonedBlockObject let, switch, catch, for
* |
* StaticBlockObject See NB
* \
* ScopeObject Engine-internal scope
* \ \ \ \
* \ \ \ StaticEvalObject Placeholder so eval scopes may be iterated through
* \ \ \
* \ \ DeclEnvObject Holds name of recursive/heavyweight named lambda
* \ \
* \ CallObject Scope of entire function or strict eval
* \
* NestedScopeObject Scope created for a statement
* \ \ \
* \ \ StaticWithObject Template for "with" object in static scope chain
* \ \
* \ DynamicWithObject Run-time "with" object on scope chain
* \
* BlockObject Shared interface of cloned/static block objects
* \ \
* \ ClonedBlockObject let, switch, catch, for
* \
* StaticBlockObject See NB
*
* This hierarchy represents more than just the interface hierarchy: reserved
* slots in base classes are fixed for all derived classes. Thus, for example,
@ -214,9 +206,6 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
* are cloned at runtime. These objects should never escape into the wild and
* support a restricted set of ScopeObject operations.
*
* NB2: StaticNonSyntacticScopeObjects notify either of 0+ non-syntactic
* DynamicWithObjects on the dynamic scope chain or a NonSyntacticScopeObject.
*
* See also "Debug scope objects" below.
*/
@ -351,10 +340,12 @@ class DeclEnvObject : public ScopeObject
public:
static const uint32_t RESERVED_SLOTS = 2;
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
static const Class class_;
static DeclEnvObject*
createTemplateObject(JSContext* cx, HandleFunction fun, NewObjectKind newKind);
createTemplateObject(JSContext* cx, HandleFunction fun, gc::InitialHeap heap);
static DeclEnvObject* create(JSContext* cx, HandleObject enclosing, HandleFunction callee);
@ -363,15 +354,16 @@ class DeclEnvObject : public ScopeObject
}
};
// Static eval scope placeholder objects on the static scope chain. Created at
// the time of compiling the eval script, and set as its static enclosing
// scope.
// Static eval scope template objects on the static scope. Created at the
// time of compiling the eval script, and set as its static enclosing scope.
class StaticEvalObject : public ScopeObject
{
static const uint32_t STRICT_SLOT = 1;
public:
static const unsigned RESERVED_SLOTS = 2;
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
static const Class class_;
static StaticEvalObject* create(JSContext* cx, HandleObject enclosing);
@ -395,42 +387,6 @@ class StaticEvalObject : public ScopeObject
}
};
// Static scope objects that stand in for one or more "polluting global"
// scopes on the dynamic scope chain.
//
// There are two flavors of polluting global scopes on the dynamic scope
// chain: either 0+ non-syntactic DynamicWithObjects, or 1
// NonSyntacticVariablesObject, created exclusively in
// js::ExecuteInGlobalAndReturnScope.
class StaticNonSyntacticScopeObjects : public ScopeObject
{
public:
static const unsigned RESERVED_SLOTS = 1;
static const Class class_;
static StaticNonSyntacticScopeObjects* create(JSContext* cx, HandleObject enclosing);
JSObject* enclosingScopeForStaticScopeIter() {
return getReservedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
}
};
// A non-syntactic dynamic scope object that captures non-lexical
// bindings. That is, a scope object that captures both qualified var
// assignments and unqualified bareword assignments. Its parent is always the
// real global.
//
// This is used in ExecuteInGlobalAndReturnScope and sits in front of the
// global scope to capture 'var' and bareword asignments.
class NonSyntacticVariablesObject : public ScopeObject
{
public:
static const unsigned RESERVED_SLOTS = 1;
static const Class class_;
static NonSyntacticVariablesObject* create(JSContext* cx, Handle<GlobalObject*> global);
};
class NestedScopeObject : public ScopeObject
{
public:
@ -480,6 +436,8 @@ class StaticWithObject : public NestedScopeObject
{
public:
static const unsigned RESERVED_SLOTS = 1;
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
static const Class class_;
static StaticWithObject* create(ExclusiveContext* cx);
@ -494,6 +452,8 @@ class DynamicWithObject : public NestedScopeObject
public:
static const unsigned RESERVED_SLOTS = 4;
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT4_BACKGROUND;
static const Class class_;
enum WithKind {
@ -545,6 +505,8 @@ class BlockObject : public NestedScopeObject
public:
static const unsigned RESERVED_SLOTS = 2;
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT4_BACKGROUND;
static const Class class_;
/* Return the abstract stack depth right before entering this nested scope. */
@ -631,7 +593,7 @@ class StaticBlockObject : public BlockObject
* variable of the block isAliased.
*/
bool needsClone() {
return numVariables() > 0 && !getSlot(RESERVED_SLOTS).isFalse();
return !getFixedSlot(RESERVED_SLOTS).isFalse();
}
/* Frontend-only functions ***********************************************/
@ -735,6 +697,8 @@ class UninitializedLexicalObject : public ScopeObject
{
public:
static const unsigned RESERVED_SLOTS = 1;
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
static const Class class_;
static UninitializedLexicalObject* create(JSContext* cx, HandleObject enclosing);
@ -795,20 +759,17 @@ class ScopeIter
inline JSObject& enclosingScope() const;
// If !done():
enum Type { Call, Block, With, Eval, NonSyntactic };
enum Type { Call, Block, With, Eval };
Type type() const;
inline bool hasNonSyntacticScopeObject() const;
inline bool hasSyntacticScopeObject() const;
inline bool hasAnyScopeObject() const;
inline bool canHaveSyntacticScopeObject() const;
inline bool hasScopeObject() const;
inline bool canHaveScopeObject() const;
ScopeObject& scope() const;
JSObject* maybeStaticScope() const;
StaticBlockObject& staticBlock() const { return ssi_.block(); }
StaticWithObject& staticWith() const { return ssi_.staticWith(); }
StaticEvalObject& staticEval() const { return ssi_.eval(); }
StaticNonSyntacticScopeObjects& staticNonSyntactic() const { return ssi_.nonSyntactic(); }
JSFunction& fun() const { return ssi_.fun(); }
bool withinInitialFrame() const { return !!frame_; }
@ -1048,8 +1009,7 @@ JSObject::is<js::ScopeObject>() const
return is<js::CallObject>() ||
is<js::DeclEnvObject>() ||
is<js::NestedScopeObject>() ||
is<js::UninitializedLexicalObject>() ||
is<js::NonSyntacticVariablesObject>();
is<js::UninitializedLexicalObject>();
}
template<>
@ -1081,8 +1041,8 @@ inline bool
IsSyntacticScope(JSObject* scope)
{
return scope->is<ScopeObject>() &&
(!scope->is<DynamicWithObject>() || scope->as<DynamicWithObject>().isSyntactic()) &&
!scope->is<NonSyntacticVariablesObject>();
(!scope->is<DynamicWithObject>() ||
scope->as<DynamicWithObject>().isSyntactic());
}
inline const Value&
@ -1106,54 +1066,16 @@ ScopeIter::done() const
}
inline bool
ScopeIter::hasSyntacticScopeObject() const
ScopeIter::hasScopeObject() const
{
return ssi_.hasSyntacticDynamicScopeObject();
return ssi_.hasDynamicScopeObject();
}
inline bool
ScopeIter::hasNonSyntacticScopeObject() const
ScopeIter::canHaveScopeObject() const
{
// The case we're worrying about here is a NonSyntactic static scope which
// has 0+ corresponding non-syntactic DynamicWithObject scopes or a
// NonSyntacticVariablesObject.
if (ssi_.type() == StaticScopeIter<CanGC>::NonSyntactic) {
MOZ_ASSERT_IF(scope_->is<DynamicWithObject>(),
!scope_->as<DynamicWithObject>().isSyntactic());
return scope_->is<DynamicWithObject>() ||
scope_->is<NonSyntacticVariablesObject>();
}
return false;
}
inline bool
ScopeIter::hasAnyScopeObject() const
{
return hasSyntacticScopeObject() || hasNonSyntacticScopeObject();
}
inline bool
ScopeIter::canHaveSyntacticScopeObject() const
{
if (ssi_.done())
return false;
switch (type()) {
case Call:
return true;
case Block:
return true;
case With:
return true;
case Eval:
// Only strict eval scopes can have dynamic scope objects.
return staticEval().isStrict();
case NonSyntactic:
return false;
}
// Silence warnings.
return false;
// Non-strict eval scopes cannot have dynamic scope objects.
return !ssi_.done() && (type() != Eval || staticEval().isStrict());
}
inline JSObject&
@ -1171,12 +1093,10 @@ ScopeIter::enclosingScope() const
extern bool
CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
HandleObject dynamicTerminatingScope,
MutableHandleObject dynamicScopeObj);
bool HasNonSyntacticStaticScopeChain(JSObject* staticScope);
MutableHandleObject dynamicScopeObj,
MutableHandleObject staticScopeObj);
#ifdef DEBUG
void DumpStaticScopeChain(JSScript* script);
bool
AnalyzeEntrainedVariables(JSContext* cx, HandleScript script);
#endif

View File

@ -1722,9 +1722,7 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
js::gc::AllocKind kind = hasName
? gc::AllocKind::FUNCTION_EXTENDED
: selfHostedFunction->getAllocKind();
MOZ_ASSERT(!CanReuseScriptForClone(cx->compartment(), selfHostedFunction, cx->global()));
clone = CloneFunctionAndScript(cx, selfHostedFunction, cx->global(),
/* newStaticScope = */ nullptr, kind);
clone = CloneFunctionObject(cx, selfHostedFunction, cx->global(), kind, TenuredObject);
// To be able to re-lazify the cloned function, its name in the
// self-hosting compartment has to be stored on the clone.
if (clone && hasName)
@ -1808,17 +1806,22 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx, HandlePropertyName name,
// JSFunction::generatorKind can't handle lazy self-hosted functions, so we make sure there
// aren't any.
MOZ_ASSERT(!sourceFun->isGenerator());
MOZ_ASSERT(sourceFun->nargs() == targetFun->nargs());
// The target function might have been relazified after it's flags changed.
targetFun->setFlags((targetFun->flags() & ~JSFunction::INTERPRETED_LAZY) |
sourceFun->flags() | JSFunction::EXTENDED);
MOZ_ASSERT(targetFun->isExtended());
RootedScript sourceScript(cx, sourceFun->getOrCreateScript(cx));
if (!sourceScript)
return false;
MOZ_ASSERT(!sourceScript->enclosingStaticScope());
return !!CloneScriptIntoFunction(cx, /* enclosingScope = */ nullptr, targetFun, sourceScript);
JSScript* cscript = CloneScript(cx, nullptr, targetFun, sourceScript);
if (!cscript)
return false;
cscript->setFunction(targetFun);
MOZ_ASSERT(sourceFun->nargs() == targetFun->nargs());
// The target function might have been relazified after it's flags changed.
targetFun->setFlags((targetFun->flags() & ~JSFunction::INTERPRETED_LAZY) |
sourceFun->flags() | JSFunction::EXTENDED);
targetFun->setScript(cscript);
MOZ_ASSERT(targetFun->isExtended());
return true;
}
bool

View File

@ -153,12 +153,7 @@ AssertDynamicScopeMatchesStaticScope(JSContext* cx, JSScript* script, JSObject*
#ifdef DEBUG
RootedObject enclosingScope(cx, script->enclosingStaticScope());
for (StaticScopeIter<NoGC> i(enclosingScope); !i.done(); i++) {
if (i.type() == StaticScopeIter<NoGC>::NonSyntactic) {
while (scope->is<DynamicWithObject>() || scope->is<NonSyntacticVariablesObject>()) {
MOZ_ASSERT(!IsSyntacticScope(scope));
scope = &scope->as<ScopeObject>().enclosingScope();
}
} else if (i.hasSyntacticDynamicScopeObject()) {
if (i.hasDynamicScopeObject()) {
switch (i.type()) {
case StaticScopeIter<NoGC>::Function:
MOZ_ASSERT(scope->as<CallObject>().callee().nonLazyScript() == i.funScript());
@ -178,14 +173,13 @@ AssertDynamicScopeMatchesStaticScope(JSContext* cx, JSScript* script, JSObject*
case StaticScopeIter<NoGC>::Eval:
scope = &scope->as<CallObject>().enclosingScope();
break;
case StaticScopeIter<NoGC>::NonSyntactic:
MOZ_CRASH("NonSyntactic should not have a syntactic scope");
break;
}
}
}
MOZ_ASSERT(scope->is<GlobalObject>() || scope->is<DebugScopeObject>());
// The scope chain is always ended by one or more non-syntactic
// ScopeObjects (viz. GlobalObject or a non-syntactic WithObject).
MOZ_ASSERT(!IsSyntacticScope(scope));
#endif
}
@ -251,7 +245,8 @@ InterpreterFrame::epilogue(JSContext* cx)
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
DebugScopes::onPopStrictEvalScope(this);
} else if (isDirectEvalFrame()) {
MOZ_ASSERT_IF(isDebuggerEvalFrame(), !IsSyntacticScope(scopeChain()));
if (isDebuggerEvalFrame())
MOZ_ASSERT(!IsSyntacticScope(scopeChain()));
} else {
/*
* Debugger.Object.prototype.evalInGlobal creates indirect eval
@ -1143,7 +1138,7 @@ FrameIter::matchCallee(JSContext* cx, HandleFunction fun) const
// expect both functions to have the same JSScript. If so, and if they are
// different, then they cannot be equal.
RootedObject global(cx, &fun->global());
bool useSameScript = CanReuseScriptForClone(fun->compartment(), currentCallee, global);
bool useSameScript = CloneFunctionObjectUseSameScript(fun->compartment(), currentCallee, global);
if (useSameScript &&
(currentCallee->hasScript() != fun->hasScript() ||
currentCallee->nonLazyScript() != fun->nonLazyScript()))

View File

@ -146,10 +146,8 @@ PrepareScript(nsIURI* uri,
}
if (!reuseGlobal) {
if (JS_IsGlobalObject(targetObj))
JS::Compile(cx, options, srcBuf, script);
else
JS::CompileForNonSyntacticScope(cx, options, srcBuf, script);
options.setHasPollutedScope(!JS_IsGlobalObject(targetObj));
JS::Compile(cx, options, srcBuf, script);
} else {
AutoObjectVector scopeChain(cx);
if (!JS_IsGlobalObject(targetObj) &&
@ -164,11 +162,9 @@ PrepareScript(nsIURI* uri,
// We only use lazy source when no special encoding is specified because
// the lazy source loader doesn't know the encoding.
if (!reuseGlobal) {
options.setSourceIsLazy(true);
if (JS_IsGlobalObject(targetObj))
JS::Compile(cx, options, buf, len, script);
else
JS::CompileForNonSyntacticScope(cx, options, buf, len, script);
options.setSourceIsLazy(true)
.setHasPollutedScope(!JS_IsGlobalObject(targetObj));
JS::Compile(cx, options, buf, len, script);
} else {
AutoObjectVector scopeChain(cx);
if (!JS_IsGlobalObject(targetObj) &&