зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1677580 - Remove JSOp::Def{Var,Let,Const,Fun} opcodes. r=jandem
These are no longer generated and their behaviour is subsumed by the GlobalOrEvalDeclInstantiation. Differential Revision: https://phabricator.services.mozilla.com/D97215
This commit is contained in:
Родитель
23e9698e18
Коммит
b85ecde81f
|
@ -1373,10 +1373,6 @@ static bool BytecodeIsEffectful(JSOp op) {
|
|||
case JSOp::InitAliasedLexical:
|
||||
case JSOp::SetIntrinsic:
|
||||
case JSOp::InitGLexical:
|
||||
case JSOp::DefVar:
|
||||
case JSOp::DefLet:
|
||||
case JSOp::DefConst:
|
||||
case JSOp::DefFun:
|
||||
case JSOp::GlobalOrEvalDeclInstantiation:
|
||||
case JSOp::SetFunName:
|
||||
case JSOp::MutateProto:
|
||||
|
|
|
@ -3857,66 +3857,6 @@ bool BaselineCodeGen<Handler>::emit_SetIntrinsic() {
|
|||
return callVM<Fn, SetIntrinsicOperation>();
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_DefVar() {
|
||||
frame.syncStack(0);
|
||||
|
||||
masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushBytecodePCArg();
|
||||
pushScriptArg();
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*);
|
||||
return callVM<Fn, DefVarOperation>();
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emitDefLexical(JSOp op) {
|
||||
MOZ_ASSERT(op == JSOp::DefConst || op == JSOp::DefLet);
|
||||
|
||||
frame.syncStack(0);
|
||||
|
||||
masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushBytecodePCArg();
|
||||
pushScriptArg();
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*);
|
||||
return callVM<Fn, DefLexicalOperation>();
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_DefConst() {
|
||||
return emitDefLexical(JSOp::DefConst);
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_DefLet() {
|
||||
return emitDefLexical(JSOp::DefLet);
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_DefFun() {
|
||||
frame.popRegsAndSync(1);
|
||||
masm.unboxObject(R0, R0.scratchReg());
|
||||
masm.loadPtr(frame.addressOfEnvironmentChain(), R1.scratchReg());
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushArg(R0.scratchReg());
|
||||
pushArg(R1.scratchReg());
|
||||
pushScriptArg();
|
||||
|
||||
using Fn = bool (*)(JSContext*, HandleScript, HandleObject, HandleFunction);
|
||||
return callVM<Fn, DefFunOperation>();
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_GlobalOrEvalDeclInstantiation() {
|
||||
frame.syncStack(0);
|
||||
|
|
|
@ -231,7 +231,6 @@ class BaselineCodeGen {
|
|||
MOZ_MUST_USE bool emitSetPropSuper(bool strict);
|
||||
|
||||
MOZ_MUST_USE bool emitBindName(JSOp op);
|
||||
MOZ_MUST_USE bool emitDefLexical(JSOp op);
|
||||
|
||||
// Try to bake in the result of GETGNAME/BINDGNAME instead of using an IC.
|
||||
// Return true if we managed to optimize the op.
|
||||
|
|
|
@ -266,10 +266,6 @@ IonBytecodeInfo js::jit::AnalyzeBytecodeForIon(JSContext* cx,
|
|||
case JSOp::SetAliasedVar:
|
||||
case JSOp::Lambda:
|
||||
case JSOp::LambdaArrow:
|
||||
case JSOp::DefFun:
|
||||
case JSOp::DefVar:
|
||||
case JSOp::DefLet:
|
||||
case JSOp::DefConst:
|
||||
case JSOp::PushLexicalEnv:
|
||||
case JSOp::PopLexicalEnv:
|
||||
case JSOp::ImplicitThis:
|
||||
|
|
|
@ -6532,46 +6532,6 @@ void CodeGenerator::visitCheckOverRecursed(LCheckOverRecursed* lir) {
|
|||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitDefVar(LDefVar* lir) {
|
||||
Register envChain = ToRegister(lir->environmentChain());
|
||||
|
||||
JSScript* script = current->mir()->info().script();
|
||||
jsbytecode* pc = lir->mir()->resumePoint()->pc();
|
||||
|
||||
pushArg(ImmPtr(pc)); // jsbytecode*
|
||||
pushArg(ImmGCPtr(script)); // JSScript*
|
||||
pushArg(envChain); // JSObject*
|
||||
|
||||
using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*);
|
||||
callVM<Fn, DefVarOperation>(lir);
|
||||
}
|
||||
|
||||
void CodeGenerator::visitDefLexical(LDefLexical* lir) {
|
||||
Register envChain = ToRegister(lir->environmentChain());
|
||||
|
||||
JSScript* script = current->mir()->info().script();
|
||||
jsbytecode* pc = lir->mir()->resumePoint()->pc();
|
||||
|
||||
pushArg(ImmPtr(pc)); // jsbytecode*
|
||||
pushArg(ImmGCPtr(script)); // JSScript*
|
||||
pushArg(envChain); // JSObject*
|
||||
|
||||
using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*);
|
||||
callVM<Fn, DefLexicalOperation>(lir);
|
||||
}
|
||||
|
||||
void CodeGenerator::visitDefFun(LDefFun* lir) {
|
||||
Register envChain = ToRegister(lir->environmentChain());
|
||||
|
||||
Register fun = ToRegister(lir->fun());
|
||||
pushArg(fun);
|
||||
pushArg(envChain);
|
||||
pushArg(ImmGCPtr(current->mir()->info().script()));
|
||||
|
||||
using Fn = bool (*)(JSContext*, HandleScript, HandleObject, HandleFunction);
|
||||
callVM<Fn, DefFunOperation>(lir);
|
||||
}
|
||||
|
||||
void CodeGenerator::visitCheckOverRecursedFailure(
|
||||
CheckOverRecursedFailure* ool) {
|
||||
// The OOL path is hit if the recursion depth has been exceeded.
|
||||
|
|
|
@ -128,30 +128,6 @@ void LIRGenerator::visitCheckOverRecursed(MCheckOverRecursed* ins) {
|
|||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitDefVar(MDefVar* ins) {
|
||||
LDefVar* lir =
|
||||
new (alloc()) LDefVar(useRegisterAtStart(ins->environmentChain()));
|
||||
add(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitDefLexical(MDefLexical* ins) {
|
||||
LDefLexical* lir =
|
||||
new (alloc()) LDefLexical(useRegisterAtStart(ins->environmentChain()));
|
||||
add(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitDefFun(MDefFun* ins) {
|
||||
MDefinition* fun = ins->fun();
|
||||
MOZ_ASSERT(fun->type() == MIRType::Object);
|
||||
|
||||
LDefFun* lir = new (alloc()) LDefFun(
|
||||
useRegisterAtStart(fun), useRegisterAtStart(ins->environmentChain()));
|
||||
add(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitNewArray(MNewArray* ins) {
|
||||
LNewArray* lir = new (alloc()) LNewArray(temp());
|
||||
define(lir, ins);
|
||||
|
|
|
@ -6799,46 +6799,6 @@ class MGlobalDeclInstantiation : public MNullaryInstruction {
|
|||
TRIVIAL_NEW_WRAPPERS
|
||||
};
|
||||
|
||||
// If not defined, set a global variable to |undefined|.
|
||||
class MDefVar : public MUnaryInstruction, public NoTypePolicy::Data {
|
||||
private:
|
||||
explicit MDefVar(MDefinition* envChain)
|
||||
: MUnaryInstruction(classOpcode, envChain) {}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(DefVar)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, environmentChain))
|
||||
|
||||
bool possiblyCalls() const override { return true; }
|
||||
};
|
||||
|
||||
class MDefLexical : public MUnaryInstruction, public NoTypePolicy::Data {
|
||||
private:
|
||||
explicit MDefLexical(MDefinition* envChain)
|
||||
: MUnaryInstruction(classOpcode, envChain) {}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(DefLexical)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, environmentChain))
|
||||
|
||||
bool possiblyCalls() const override { return true; }
|
||||
};
|
||||
|
||||
class MDefFun : public MBinaryInstruction, public ObjectPolicy<0>::Data {
|
||||
private:
|
||||
MDefFun(MDefinition* fun, MDefinition* envChain)
|
||||
: MBinaryInstruction(classOpcode, fun, envChain) {}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(DefFun)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, fun), (1, environmentChain))
|
||||
|
||||
bool possiblyCalls() const override { return true; }
|
||||
};
|
||||
|
||||
class MRegExp : public MNullaryInstruction {
|
||||
CompilerGCPointer<RegExpObject*> source_;
|
||||
bool hasShared_;
|
||||
|
|
|
@ -105,9 +105,6 @@ namespace jit {
|
|||
_(DebugLeaveThenRecreateLexicalEnv, \
|
||||
js::jit::DebugLeaveThenRecreateLexicalEnv) \
|
||||
_(Debug_CheckSelfHosted, js::Debug_CheckSelfHosted) \
|
||||
_(DefFunOperation, js::DefFunOperation) \
|
||||
_(DefLexicalOperation, js::DefLexicalOperation) \
|
||||
_(DefVarOperation, js::DefVarOperation) \
|
||||
_(DelElemOperationNonStrict, js::DelElemOperation<false>) \
|
||||
_(DelElemOperationStrict, js::DelElemOperation<true>) \
|
||||
_(DelPropOperationNonStrict, js::DelPropOperation<false>) \
|
||||
|
|
|
@ -1530,42 +1530,6 @@ bool WarpBuilder::usesEnvironmentChain() const {
|
|||
return script_->jitScript()->usesEnvironmentChain();
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_DefVar(BytecodeLocation loc) {
|
||||
MOZ_ASSERT(usesEnvironmentChain());
|
||||
|
||||
MDefinition* env = current->environmentChain();
|
||||
MDefVar* defvar = MDefVar::New(alloc(), env);
|
||||
current->add(defvar);
|
||||
return resumeAfter(defvar, loc);
|
||||
}
|
||||
|
||||
bool WarpBuilder::buildDefLexicalOp(BytecodeLocation loc) {
|
||||
MOZ_ASSERT(usesEnvironmentChain());
|
||||
|
||||
MDefinition* env = current->environmentChain();
|
||||
MDefLexical* defLexical = MDefLexical::New(alloc(), env);
|
||||
current->add(defLexical);
|
||||
return resumeAfter(defLexical, loc);
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_DefLet(BytecodeLocation loc) {
|
||||
return buildDefLexicalOp(loc);
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_DefConst(BytecodeLocation loc) {
|
||||
return buildDefLexicalOp(loc);
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_DefFun(BytecodeLocation loc) {
|
||||
MOZ_ASSERT(usesEnvironmentChain());
|
||||
|
||||
MDefinition* fun = current->pop();
|
||||
MDefinition* env = current->environmentChain();
|
||||
MDefFun* deffun = MDefFun::New(alloc(), fun, env);
|
||||
current->add(deffun);
|
||||
return resumeAfter(deffun, loc);
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_GlobalOrEvalDeclInstantiation(BytecodeLocation loc) {
|
||||
MOZ_ASSERT(!script_->isForEval(), "Eval scripts not supported");
|
||||
auto* redeclCheck = MGlobalDeclInstantiation::New(alloc());
|
||||
|
|
|
@ -303,7 +303,6 @@ class MOZ_STACK_CLASS WarpBuilder : public WarpBuilderShared {
|
|||
MOZ_MUST_USE bool buildBinaryOp(BytecodeLocation loc);
|
||||
MOZ_MUST_USE bool buildCompareOp(BytecodeLocation loc);
|
||||
MOZ_MUST_USE bool buildTestOp(BytecodeLocation loc);
|
||||
MOZ_MUST_USE bool buildDefLexicalOp(BytecodeLocation loc);
|
||||
MOZ_MUST_USE bool buildCallOp(BytecodeLocation loc);
|
||||
|
||||
MOZ_MUST_USE bool buildInitPropGetterSetterOp(BytecodeLocation loc);
|
||||
|
|
|
@ -660,10 +660,6 @@ AbortReasonOr<WarpScriptSnapshot*> WarpScriptOracle::createScriptSnapshot() {
|
|||
case JSOp::DynamicImport:
|
||||
case JSOp::Not:
|
||||
case JSOp::ToString:
|
||||
case JSOp::DefVar:
|
||||
case JSOp::DefLet:
|
||||
case JSOp::DefConst:
|
||||
case JSOp::DefFun:
|
||||
case JSOp::GlobalOrEvalDeclInstantiation:
|
||||
case JSOp::BindVar:
|
||||
case JSOp::MutateProto:
|
||||
|
|
|
@ -662,47 +662,6 @@ class LWasmInterruptCheck : public LInstructionHelper<0, 1, 0> {
|
|||
const LAllocation* tlsPtr() { return getOperand(0); }
|
||||
};
|
||||
|
||||
class LDefVar : public LCallInstructionHelper<0, 1, 0> {
|
||||
public:
|
||||
LIR_HEADER(DefVar)
|
||||
|
||||
explicit LDefVar(const LAllocation& envChain)
|
||||
: LCallInstructionHelper(classOpcode) {
|
||||
setOperand(0, envChain);
|
||||
}
|
||||
|
||||
const LAllocation* environmentChain() { return getOperand(0); }
|
||||
MDefVar* mir() const { return mir_->toDefVar(); }
|
||||
};
|
||||
|
||||
class LDefLexical : public LCallInstructionHelper<0, 1, 0> {
|
||||
public:
|
||||
LIR_HEADER(DefLexical)
|
||||
|
||||
explicit LDefLexical(const LAllocation& envChain)
|
||||
: LCallInstructionHelper(classOpcode) {
|
||||
setOperand(0, envChain);
|
||||
}
|
||||
|
||||
const LAllocation* environmentChain() { return getOperand(0); }
|
||||
MDefLexical* mir() const { return mir_->toDefLexical(); }
|
||||
};
|
||||
|
||||
class LDefFun : public LCallInstructionHelper<0, 2, 0> {
|
||||
public:
|
||||
LIR_HEADER(DefFun)
|
||||
|
||||
LDefFun(const LAllocation& fun, const LAllocation& envChain)
|
||||
: LCallInstructionHelper(classOpcode) {
|
||||
setOperand(0, fun);
|
||||
setOperand(1, envChain);
|
||||
}
|
||||
|
||||
const LAllocation* fun() { return getOperand(0); }
|
||||
const LAllocation* environmentChain() { return getOperand(1); }
|
||||
MDefFun* mir() const { return mir_->toDefFun(); }
|
||||
};
|
||||
|
||||
class LTypeOfV : public LInstructionHelper<1, BOX_PIECES, 1> {
|
||||
public:
|
||||
LIR_HEADER(TypeOfV)
|
||||
|
|
|
@ -3722,39 +3722,6 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
|
|||
}
|
||||
END_CASE(SetLocal)
|
||||
|
||||
CASE(DefVar) {
|
||||
HandleObject env = REGS.fp()->environmentChain();
|
||||
if (!DefVarOperation(cx, env, script, REGS.pc)) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
END_CASE(DefVar)
|
||||
|
||||
CASE(DefConst)
|
||||
CASE(DefLet) {
|
||||
HandleObject env = REGS.fp()->environmentChain();
|
||||
if (!DefLexicalOperation(cx, env, script, REGS.pc)) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
END_CASE(DefLet)
|
||||
|
||||
CASE(DefFun) {
|
||||
/*
|
||||
* A top-level function defined in Global or Eval code (see ECMA-262
|
||||
* Ed. 3), or else a SpiderMonkey extension: a named function statement
|
||||
* in a compound statement (not at the top statement level of global
|
||||
* code, or at the top level of a function body).
|
||||
*/
|
||||
ReservedRooted<JSFunction*> fun(&rootFunction0,
|
||||
®S.sp[-1].toObject().as<JSFunction>());
|
||||
if (!DefFunOperation(cx, script, REGS.fp()->environmentChain(), fun)) {
|
||||
goto error;
|
||||
}
|
||||
REGS.sp--;
|
||||
}
|
||||
END_CASE(DefFun)
|
||||
|
||||
CASE(GlobalOrEvalDeclInstantiation) {
|
||||
GCThingIndex lastFun = GET_GCTHING_INDEX(REGS.pc);
|
||||
HandleObject env = REGS.fp()->environmentChain();
|
||||
|
@ -4713,175 +4680,6 @@ JSObject* js::BindVarOperation(JSContext* cx, JSObject* envChain) {
|
|||
return &GetVariablesObject(envChain);
|
||||
}
|
||||
|
||||
bool js::DefVarOperation(JSContext* cx, HandleObject envChain,
|
||||
HandleScript script, jsbytecode* pc) {
|
||||
MOZ_ASSERT(JSOp(*pc) == JSOp::DefVar);
|
||||
|
||||
RootedObject varobj(cx, &GetVariablesObject(envChain));
|
||||
MOZ_ASSERT(varobj->isQualifiedVarObj());
|
||||
|
||||
RootedPropertyName name(cx, script->getName(pc));
|
||||
|
||||
unsigned attrs = JSPROP_ENUMERATE;
|
||||
if (!script->isForEval()) {
|
||||
attrs |= JSPROP_PERMANENT;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Per spec, it is an error to redeclare a lexical binding. This should
|
||||
// have already been checked.
|
||||
if (JS_HasExtensibleLexicalEnvironment(varobj)) {
|
||||
Rooted<LexicalEnvironmentObject*> lexicalEnv(cx);
|
||||
lexicalEnv = &JS_ExtensibleLexicalEnvironment(varobj)
|
||||
->as<LexicalEnvironmentObject>();
|
||||
MOZ_ASSERT(CheckVarNameConflict(cx, lexicalEnv, name));
|
||||
}
|
||||
#endif
|
||||
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject obj2(cx);
|
||||
if (!LookupProperty(cx, varobj, name, &obj2, &prop)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Steps 8c, 8d. */
|
||||
if (!prop || (obj2 != varobj && varobj->is<GlobalObject>())) {
|
||||
if (!DefineDataProperty(cx, varobj, name, UndefinedHandleValue, attrs)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (varobj->is<GlobalObject>()) {
|
||||
if (!varobj->as<GlobalObject>().realm()->addToVarNames(cx, name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool js::DefLexicalOperation(JSContext* cx, HandleObject envChain,
|
||||
HandleScript script, jsbytecode* pc) {
|
||||
MOZ_ASSERT(JSOp(*pc) == JSOp::DefLet || JSOp(*pc) == JSOp::DefConst);
|
||||
|
||||
unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
||||
if (JSOp(*pc) == JSOp::DefConst) {
|
||||
attrs |= JSPROP_READONLY;
|
||||
}
|
||||
|
||||
Rooted<LexicalEnvironmentObject*> lexicalEnv(cx);
|
||||
if (script->hasNonSyntacticScope()) {
|
||||
lexicalEnv = &NearestEnclosingExtensibleLexicalEnvironment(envChain);
|
||||
} else {
|
||||
lexicalEnv = &cx->global()->lexicalEnvironment();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
RootedObject varObj(cx);
|
||||
if (script->hasNonSyntacticScope()) {
|
||||
varObj = &GetVariablesObject(envChain);
|
||||
} else {
|
||||
varObj = cx->global();
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(!script->hasNonSyntacticScope(),
|
||||
lexicalEnv == &cx->global()->lexicalEnvironment() &&
|
||||
varObj == cx->global());
|
||||
|
||||
// Redeclaration checks should have already been done.
|
||||
RootedPropertyName name(cx, script->getName(pc));
|
||||
MOZ_ASSERT(CheckLexicalNameConflict(cx, lexicalEnv, varObj, name));
|
||||
#endif
|
||||
|
||||
RootedId id(cx, NameToId(script->getName(pc)));
|
||||
RootedValue uninitialized(cx, MagicValue(JS_UNINITIALIZED_LEXICAL));
|
||||
return NativeDefineDataProperty(cx, lexicalEnv, id, uninitialized, attrs);
|
||||
}
|
||||
|
||||
bool js::DefFunOperation(JSContext* cx, HandleScript script,
|
||||
HandleObject envChain, HandleFunction fun) {
|
||||
/*
|
||||
* We define the function as a property of the variable object and not the
|
||||
* current scope chain even for the case of function expression statements
|
||||
* and functions defined by eval inside let or with blocks.
|
||||
*/
|
||||
RootedObject parent(cx, envChain);
|
||||
while (!parent->isQualifiedVarObj()) {
|
||||
parent = parent->enclosingEnvironment();
|
||||
}
|
||||
|
||||
/* ES5 10.5 (NB: with subsequent errata). */
|
||||
RootedPropertyName name(cx, fun->explicitName()->asPropertyName());
|
||||
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject pobj(cx);
|
||||
if (!LookupProperty(cx, parent, name, &pobj, &prop)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue rval(cx, ObjectValue(*fun));
|
||||
|
||||
/*
|
||||
* ECMA requires functions defined when entering Eval code to be
|
||||
* impermanent.
|
||||
*/
|
||||
unsigned attrs = script->isForEval() ? JSPROP_ENUMERATE
|
||||
: JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
||||
|
||||
/* Steps 5d, 5f. */
|
||||
if (!prop || pobj != parent) {
|
||||
if (!DefineDataProperty(cx, parent, name, rval, attrs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parent->is<GlobalObject>()) {
|
||||
return parent->as<GlobalObject>().realm()->addToVarNames(cx, name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Step 5e.
|
||||
*
|
||||
* A DebugEnvironmentProxy is okay here, and sometimes necessary. If
|
||||
* Debugger.Frame.prototype.eval defines a function with the same name as an
|
||||
* extant variable in the frame, the DebugEnvironmentProxy takes care of
|
||||
* storing the function in the stack frame (for non-aliased variables) or on
|
||||
* the scope object (for aliased).
|
||||
*/
|
||||
MOZ_ASSERT(parent->isNative() || parent->is<DebugEnvironmentProxy>());
|
||||
if (parent->is<GlobalObject>()) {
|
||||
Shape* shape = prop.shape();
|
||||
if (shape->configurable()) {
|
||||
if (!DefineDataProperty(cx, parent, name, rval, attrs)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(shape->isDataDescriptor());
|
||||
MOZ_ASSERT(shape->writable());
|
||||
MOZ_ASSERT(shape->enumerable());
|
||||
}
|
||||
|
||||
// Careful: the presence of a shape, even one appearing to derive from
|
||||
// a variable declaration, doesn't mean it's in [[VarNames]].
|
||||
if (!parent->as<GlobalObject>().realm()->addToVarNames(cx, name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-global properties, and global properties which we aren't simply
|
||||
* redefining, must be set. First, this preserves their attributes.
|
||||
* Second, this will produce warnings and/or errors as necessary if the
|
||||
* specified Call object property is not writable (const).
|
||||
*/
|
||||
|
||||
/* Step 5f. */
|
||||
RootedId id(cx, NameToId(name));
|
||||
return PutProperty(cx, parent, id, rval, script->strict());
|
||||
}
|
||||
|
||||
JSObject* js::ImportMetaOperation(JSContext* cx, HandleScript script) {
|
||||
RootedObject module(cx, GetModuleObjectForScript(script));
|
||||
MOZ_ASSERT(module);
|
||||
|
|
|
@ -581,15 +581,6 @@ bool DelElemOperation(JSContext* cx, HandleValue val, HandleValue index,
|
|||
|
||||
JSObject* BindVarOperation(JSContext* cx, JSObject* envChain);
|
||||
|
||||
bool DefVarOperation(JSContext* cx, HandleObject envChain, HandleScript script,
|
||||
jsbytecode* pc);
|
||||
|
||||
bool DefLexicalOperation(JSContext* cx, HandleObject envChain,
|
||||
HandleScript script, jsbytecode* pc);
|
||||
|
||||
bool DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain,
|
||||
HandleFunction funArg);
|
||||
|
||||
JSObject* SingletonObjectLiteralOperation(JSContext* cx, HandleScript script,
|
||||
jsbytecode* pc);
|
||||
|
||||
|
|
|
@ -3326,72 +3326,6 @@
|
|||
* Stack: => env
|
||||
*/ \
|
||||
MACRO(BindVar, bind_var, NULL, 1, 0, 1, JOF_BYTE) \
|
||||
/*
|
||||
* Create a new binding on the current VariableEnvironment (the environment
|
||||
* on the environment chain designated to receive new variables).
|
||||
*
|
||||
* `JSOp::Def{Var,Let,Const,Fun}` instructions must appear in the script
|
||||
* before anything else that might add bindings to the environment, and
|
||||
* only once per binding. There must be a correct entry for the new binding
|
||||
* in `script->bodyScope()`. (All this ensures that at run time, there is
|
||||
* no existing conflicting binding. This is checked by the
|
||||
* `JSOp::GlobalOrEvalDeclInstantiation` bytecode instruction that must
|
||||
* appear before `JSOp::Def{Var,Let,Const,Fun}`.)
|
||||
*
|
||||
* Throw a SyntaxError if the current VariableEnvironment is the global
|
||||
* environment and a binding with the same name exists on the global
|
||||
* lexical environment.
|
||||
*
|
||||
* This is used for global scripts and also in some cases for function
|
||||
* scripts where use of dynamic scoping inhibits optimization.
|
||||
*
|
||||
* Category: Variables and scopes
|
||||
* Type: Creating and deleting bindings
|
||||
* Operands: uint32_t nameIndex
|
||||
* Stack: =>
|
||||
*/ \
|
||||
MACRO(DefVar, def_var, NULL, 5, 0, 0, JOF_ATOM) \
|
||||
/*
|
||||
* Create a new binding for the given function on the current scope.
|
||||
*
|
||||
* `fun` must be a function object with an explicit name. The new
|
||||
* variable's name is `fun->explicitName()`, and its value is `fun`. In
|
||||
* global scope, this creates a new property on the global object.
|
||||
*
|
||||
* Implements: The body of the loop in [GlobalDeclarationInstantiation][1]
|
||||
* step 17 ("For each Parse Node *f* in *functionsToInitialize*...") and
|
||||
* the corresponding loop in [EvalDeclarationInstantiation][2].
|
||||
*
|
||||
* [1]: https://tc39.es/ecma262/#sec-globaldeclarationinstantiation
|
||||
* [2]: https://tc39.es/ecma262/#sec-evaldeclarationinstantiation
|
||||
*
|
||||
* Category: Variables and scopes
|
||||
* Type: Creating and deleting bindings
|
||||
* Operands:
|
||||
* Stack: fun =>
|
||||
*/ \
|
||||
MACRO(DefFun, def_fun, NULL, 1, 1, 0, JOF_BYTE) \
|
||||
/*
|
||||
* Create a new uninitialized mutable binding in the global lexical
|
||||
* environment. Throw a SyntaxError if a binding with the same name already
|
||||
* exists on that environment, or if a var binding with the same name
|
||||
* exists on the global.
|
||||
*
|
||||
* Category: Variables and scopes
|
||||
* Type: Creating and deleting bindings
|
||||
* Operands: uint32_t nameIndex
|
||||
* Stack: =>
|
||||
*/ \
|
||||
MACRO(DefLet, def_let, NULL, 5, 0, 0, JOF_ATOM) \
|
||||
/*
|
||||
* Like `DefLet`, but create an uninitialized constant binding.
|
||||
*
|
||||
* Category: Variables and scopes
|
||||
* Type: Creating and deleting bindings
|
||||
* Operands: uint32_t nameIndex
|
||||
* Stack: =>
|
||||
*/ \
|
||||
MACRO(DefConst, def_const, NULL, 5, 0, 0, JOF_ATOM) \
|
||||
/*
|
||||
* Check for conflicting bindings and then initialize them in global or
|
||||
* sloppy eval scripts. This is required for global scripts with any
|
||||
|
@ -3685,6 +3619,10 @@
|
|||
* a power of two. Use this macro to do so.
|
||||
*/
|
||||
#define FOR_EACH_TRAILING_UNUSED_OPCODE(MACRO) \
|
||||
MACRO(235) \
|
||||
MACRO(236) \
|
||||
MACRO(237) \
|
||||
MACRO(238) \
|
||||
MACRO(239) \
|
||||
MACRO(240) \
|
||||
MACRO(241) \
|
||||
|
|
Загрузка…
Ссылка в новой задаче