зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1511891 part 6 - Merge two DefLexicalOperation functions into one and have the JITs call it directly. r=tcampbell
Differential Revision: https://phabricator.services.mozilla.com/D13704 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
b9ee882ac8
Коммит
6032002978
|
@ -3092,10 +3092,10 @@ bool BaselineCodeGen<Handler>::emit_JSOP_DEFVAR() {
|
||||||
return callVM(DefVarInfo);
|
return callVM(DefVarInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*DefLexicalFn)(JSContext*, HandlePropertyName, unsigned,
|
typedef bool (*DefLexicalFn)(JSContext*, HandleObject, HandleScript,
|
||||||
HandleObject);
|
jsbytecode*);
|
||||||
static const VMFunction DefLexicalInfo =
|
static const VMFunction DefLexicalInfo =
|
||||||
FunctionInfo<DefLexicalFn>(DefLexical, "DefLexical");
|
FunctionInfo<DefLexicalFn>(DefLexicalOperation, "DefLexicalOperation");
|
||||||
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
bool BaselineCodeGen<Handler>::emitDefLexical(JSOp op) {
|
bool BaselineCodeGen<Handler>::emitDefLexical(JSOp op) {
|
||||||
|
@ -3103,19 +3103,13 @@ bool BaselineCodeGen<Handler>::emitDefLexical(JSOp op) {
|
||||||
|
|
||||||
frame.syncStack(0);
|
frame.syncStack(0);
|
||||||
|
|
||||||
unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
|
||||||
if (op == JSOP_DEFCONST) {
|
|
||||||
attrs |= JSPROP_READONLY;
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(attrs <= UINT32_MAX);
|
|
||||||
|
|
||||||
masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
|
masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
|
||||||
|
|
||||||
prepareVMCall();
|
prepareVMCall();
|
||||||
|
|
||||||
|
pushArg(ImmPtr(pc));
|
||||||
|
pushArg(ImmGCPtr(script));
|
||||||
pushArg(R0.scratchReg());
|
pushArg(R0.scratchReg());
|
||||||
pushArg(Imm32(attrs));
|
|
||||||
pushArg(ImmGCPtr(script->getName(pc)));
|
|
||||||
|
|
||||||
return callVM(DefLexicalInfo);
|
return callVM(DefLexicalInfo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,6 +176,8 @@ bool BytecodeAnalysis::init(TempAllocator& alloc, GSNCache& gsn) {
|
||||||
case JSOP_LAMBDA_ARROW:
|
case JSOP_LAMBDA_ARROW:
|
||||||
case JSOP_DEFFUN:
|
case JSOP_DEFFUN:
|
||||||
case JSOP_DEFVAR:
|
case JSOP_DEFVAR:
|
||||||
|
case JSOP_DEFLET:
|
||||||
|
case JSOP_DEFCONST:
|
||||||
case JSOP_PUSHLEXICALENV:
|
case JSOP_PUSHLEXICALENV:
|
||||||
case JSOP_POPLEXICALENV:
|
case JSOP_POPLEXICALENV:
|
||||||
case JSOP_IMPLICITTHIS:
|
case JSOP_IMPLICITTHIS:
|
||||||
|
|
|
@ -5420,13 +5420,20 @@ void CodeGenerator::visitDefVar(LDefVar* lir) {
|
||||||
callVM(DefVarInfo, lir);
|
callVM(DefVarInfo, lir);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*DefLexicalFn)(JSContext*, HandlePropertyName, unsigned);
|
typedef bool (*DefLexicalFn)(JSContext*, HandleObject, HandleScript,
|
||||||
|
jsbytecode*);
|
||||||
static const VMFunction DefLexicalInfo =
|
static const VMFunction DefLexicalInfo =
|
||||||
FunctionInfo<DefLexicalFn>(DefGlobalLexical, "DefGlobalLexical");
|
FunctionInfo<DefLexicalFn>(DefLexicalOperation, "DefLexicalOperation");
|
||||||
|
|
||||||
void CodeGenerator::visitDefLexical(LDefLexical* lir) {
|
void CodeGenerator::visitDefLexical(LDefLexical* lir) {
|
||||||
pushArg(Imm32(lir->mir()->attrs())); // unsigned
|
Register envChain = ToRegister(lir->environmentChain());
|
||||||
pushArg(ImmGCPtr(lir->mir()->name())); // PropertyName*
|
|
||||||
|
JSScript* script = current->mir()->info().script();
|
||||||
|
jsbytecode* pc = lir->mir()->resumePoint()->pc();
|
||||||
|
|
||||||
|
pushArg(ImmPtr(pc)); // jsbytecode*
|
||||||
|
pushArg(ImmGCPtr(script)); // JSScript*
|
||||||
|
pushArg(envChain); // JSObject*
|
||||||
|
|
||||||
callVM(DefLexicalInfo, lir);
|
callVM(DefLexicalInfo, lir);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1915,11 +1915,11 @@ AbortReasonOr<Ok> IonBuilder::inspectOpcode(JSOp op) {
|
||||||
return jsop_tostring();
|
return jsop_tostring();
|
||||||
|
|
||||||
case JSOP_DEFVAR:
|
case JSOP_DEFVAR:
|
||||||
return jsop_defvar(GET_UINT32_INDEX(pc));
|
return jsop_defvar();
|
||||||
|
|
||||||
case JSOP_DEFLET:
|
case JSOP_DEFLET:
|
||||||
case JSOP_DEFCONST:
|
case JSOP_DEFCONST:
|
||||||
return jsop_deflexical(GET_UINT32_INDEX(pc));
|
return jsop_deflexical();
|
||||||
|
|
||||||
case JSOP_DEFFUN:
|
case JSOP_DEFFUN:
|
||||||
return jsop_deffun();
|
return jsop_deffun();
|
||||||
|
@ -12775,7 +12775,7 @@ AbortReasonOr<Ok> IonBuilder::jsop_setarg(uint32_t arg) {
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
AbortReasonOr<Ok> IonBuilder::jsop_defvar(uint32_t index) {
|
AbortReasonOr<Ok> IonBuilder::jsop_defvar() {
|
||||||
MOZ_ASSERT(JSOp(*pc) == JSOP_DEFVAR);
|
MOZ_ASSERT(JSOp(*pc) == JSOP_DEFVAR);
|
||||||
|
|
||||||
// Pass the EnvironmentChain.
|
// Pass the EnvironmentChain.
|
||||||
|
@ -12787,20 +12787,15 @@ AbortReasonOr<Ok> IonBuilder::jsop_defvar(uint32_t index) {
|
||||||
return resumeAfter(defvar);
|
return resumeAfter(defvar);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbortReasonOr<Ok> IonBuilder::jsop_deflexical(uint32_t index) {
|
AbortReasonOr<Ok> IonBuilder::jsop_deflexical() {
|
||||||
MOZ_ASSERT(!script()->hasNonSyntacticScope());
|
|
||||||
MOZ_ASSERT(JSOp(*pc) == JSOP_DEFLET || JSOp(*pc) == JSOP_DEFCONST);
|
MOZ_ASSERT(JSOp(*pc) == JSOP_DEFLET || JSOp(*pc) == JSOP_DEFCONST);
|
||||||
|
MOZ_ASSERT(usesEnvironmentChain());
|
||||||
|
|
||||||
PropertyName* name = script()->getName(index);
|
MDefinition* env = current->environmentChain();
|
||||||
unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
MDefLexical* defLexical = MDefLexical::New(alloc(), env);
|
||||||
if (JSOp(*pc) == JSOP_DEFCONST) {
|
current->add(defLexical);
|
||||||
attrs |= JSPROP_READONLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
MDefLexical* deflex = MDefLexical::New(alloc(), name, attrs);
|
return resumeAfter(defLexical);
|
||||||
current->add(deflex);
|
|
||||||
|
|
||||||
return resumeAfter(deflex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AbortReasonOr<Ok> IonBuilder::jsop_deffun() {
|
AbortReasonOr<Ok> IonBuilder::jsop_deffun() {
|
||||||
|
|
|
@ -537,8 +537,8 @@ class IonBuilder : public MIRGenerator,
|
||||||
AbortReasonOr<Ok> jsop_neg();
|
AbortReasonOr<Ok> jsop_neg();
|
||||||
AbortReasonOr<Ok> jsop_tostring();
|
AbortReasonOr<Ok> jsop_tostring();
|
||||||
AbortReasonOr<Ok> jsop_setarg(uint32_t arg);
|
AbortReasonOr<Ok> jsop_setarg(uint32_t arg);
|
||||||
AbortReasonOr<Ok> jsop_defvar(uint32_t index);
|
AbortReasonOr<Ok> jsop_defvar();
|
||||||
AbortReasonOr<Ok> jsop_deflexical(uint32_t index);
|
AbortReasonOr<Ok> jsop_deflexical();
|
||||||
AbortReasonOr<Ok> jsop_deffun();
|
AbortReasonOr<Ok> jsop_deffun();
|
||||||
AbortReasonOr<Ok> jsop_notearg();
|
AbortReasonOr<Ok> jsop_notearg();
|
||||||
AbortReasonOr<Ok> jsop_throwsetconst();
|
AbortReasonOr<Ok> jsop_throwsetconst();
|
||||||
|
|
|
@ -141,7 +141,8 @@ void LIRGenerator::visitDefVar(MDefVar* ins) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LIRGenerator::visitDefLexical(MDefLexical* ins) {
|
void LIRGenerator::visitDefLexical(MDefLexical* ins) {
|
||||||
LDefLexical* lir = new (alloc()) LDefLexical();
|
LDefLexical* lir =
|
||||||
|
new (alloc()) LDefLexical(useRegisterAtStart(ins->environmentChain()));
|
||||||
add(lir, ins);
|
add(lir, ins);
|
||||||
assignSafepoint(lir, ins);
|
assignSafepoint(lir, ins);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6318,23 +6318,17 @@ class MDefVar : public MUnaryInstruction, public NoTypePolicy::Data {
|
||||||
bool possiblyCalls() const override { return true; }
|
bool possiblyCalls() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class MDefLexical : public MNullaryInstruction {
|
class MDefLexical : public MUnaryInstruction, public NoTypePolicy::Data {
|
||||||
CompilerPropertyName name_; // Target name to be defined.
|
|
||||||
unsigned attrs_; // Attributes to be set.
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MDefLexical(PropertyName* name, unsigned attrs)
|
explicit MDefLexical(MDefinition* envChain)
|
||||||
: MNullaryInstruction(classOpcode), name_(name), attrs_(attrs) {}
|
: MUnaryInstruction(classOpcode, envChain) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
INSTRUCTION_HEADER(DefLexical)
|
INSTRUCTION_HEADER(DefLexical)
|
||||||
TRIVIAL_NEW_WRAPPERS
|
TRIVIAL_NEW_WRAPPERS
|
||||||
|
NAMED_OPERANDS((0, environmentChain))
|
||||||
|
|
||||||
PropertyName* name() const { return name_; }
|
bool possiblyCalls() const override { return true; }
|
||||||
unsigned attrs() const { return attrs_; }
|
|
||||||
bool appendRoots(MRootList& roots) const override {
|
|
||||||
return roots.append(name_);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MDefFun : public MBinaryInstruction, public ObjectPolicy<0>::Data {
|
class MDefFun : public MBinaryInstruction, public ObjectPolicy<0>::Data {
|
||||||
|
|
|
@ -189,23 +189,6 @@ bool CheckOverRecursedBaseline(JSContext* cx, BaselineFrame* frame) {
|
||||||
return CheckOverRecursed(cx);
|
return CheckOverRecursed(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DefLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs,
|
|
||||||
HandleObject envChain) {
|
|
||||||
// Find the extensible lexical scope.
|
|
||||||
Rooted<LexicalEnvironmentObject*> lexicalEnv(
|
|
||||||
cx, &NearestEnclosingExtensibleLexicalEnvironment(envChain));
|
|
||||||
|
|
||||||
// Find the variables object.
|
|
||||||
RootedObject varObj(cx, &GetVariablesObject(envChain));
|
|
||||||
return DefLexicalOperation(cx, lexicalEnv, varObj, dn, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DefGlobalLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs) {
|
|
||||||
Rooted<LexicalEnvironmentObject*> globalLexical(
|
|
||||||
cx, &cx->global()->lexicalEnvironment());
|
|
||||||
return DefLexicalOperation(cx, globalLexical, cx->global(), dn, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MutatePrototype(JSContext* cx, HandlePlainObject obj, HandleValue value) {
|
bool MutatePrototype(JSContext* cx, HandlePlainObject obj, HandleValue value) {
|
||||||
if (!value.isObjectOrNull()) {
|
if (!value.isObjectOrNull()) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -921,10 +921,6 @@ bool InvokeFromInterpreterStub(JSContext* cx,
|
||||||
bool CheckOverRecursed(JSContext* cx);
|
bool CheckOverRecursed(JSContext* cx);
|
||||||
bool CheckOverRecursedBaseline(JSContext* cx, BaselineFrame* frame);
|
bool CheckOverRecursedBaseline(JSContext* cx, BaselineFrame* frame);
|
||||||
|
|
||||||
MOZ_MUST_USE bool DefLexical(JSContext* cx, HandlePropertyName dn,
|
|
||||||
unsigned attrs, HandleObject scopeChain);
|
|
||||||
MOZ_MUST_USE bool DefGlobalLexical(JSContext* cx, HandlePropertyName dn,
|
|
||||||
unsigned attrs);
|
|
||||||
MOZ_MUST_USE bool MutatePrototype(JSContext* cx, HandlePlainObject obj,
|
MOZ_MUST_USE bool MutatePrototype(JSContext* cx, HandlePlainObject obj,
|
||||||
HandleValue value);
|
HandleValue value);
|
||||||
MOZ_MUST_USE bool InitProp(JSContext* cx, HandleObject obj,
|
MOZ_MUST_USE bool InitProp(JSContext* cx, HandleObject obj,
|
||||||
|
|
|
@ -712,12 +712,16 @@ class LDefVar : public LCallInstructionHelper<0, 1, 0> {
|
||||||
MDefVar* mir() const { return mir_->toDefVar(); }
|
MDefVar* mir() const { return mir_->toDefVar(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class LDefLexical : public LCallInstructionHelper<0, 0, 0> {
|
class LDefLexical : public LCallInstructionHelper<0, 1, 0> {
|
||||||
public:
|
public:
|
||||||
LIR_HEADER(DefLexical)
|
LIR_HEADER(DefLexical)
|
||||||
|
|
||||||
LDefLexical() : LCallInstructionHelper(classOpcode) {}
|
explicit LDefLexical(const LAllocation& envChain)
|
||||||
|
: LCallInstructionHelper(classOpcode) {
|
||||||
|
setOperand(0, envChain);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LAllocation* environmentChain() { return getOperand(0); }
|
||||||
MDefLexical* mir() const { return mir_->toDefLexical(); }
|
MDefLexical* mir() const { return mir_->toDefLexical(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4622,35 +4622,27 @@ bool js::DefVarOperation(JSContext* cx, HandleObject envChain,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool js::DefLexicalOperation(JSContext* cx,
|
|
||||||
Handle<LexicalEnvironmentObject*> lexicalEnv,
|
|
||||||
HandleObject varObj, HandlePropertyName name,
|
|
||||||
unsigned attrs) {
|
|
||||||
// Redeclaration checks should have already been done.
|
|
||||||
MOZ_ASSERT(CheckLexicalNameConflict(cx, lexicalEnv, varObj, name));
|
|
||||||
RootedId id(cx, NameToId(name));
|
|
||||||
RootedValue uninitialized(cx, MagicValue(JS_UNINITIALIZED_LEXICAL));
|
|
||||||
return NativeDefineDataProperty(cx, lexicalEnv, id, uninitialized, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool js::DefLexicalOperation(JSContext* cx, HandleObject envChain,
|
bool js::DefLexicalOperation(JSContext* cx, HandleObject envChain,
|
||||||
HandleScript script, jsbytecode* pc) {
|
HandleScript script, jsbytecode* pc) {
|
||||||
MOZ_ASSERT(*pc == JSOP_DEFLET || *pc == JSOP_DEFCONST);
|
MOZ_ASSERT(*pc == JSOP_DEFLET || *pc == JSOP_DEFCONST);
|
||||||
|
|
||||||
RootedPropertyName name(cx, script->getName(pc));
|
|
||||||
|
|
||||||
unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
||||||
if (*pc == JSOP_DEFCONST) {
|
if (*pc == JSOP_DEFCONST) {
|
||||||
attrs |= JSPROP_READONLY;
|
attrs |= JSPROP_READONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rooted<LexicalEnvironmentObject*> lexicalEnv(cx);
|
Rooted<LexicalEnvironmentObject*> lexicalEnv(cx);
|
||||||
RootedObject varObj(cx);
|
|
||||||
if (script->hasNonSyntacticScope()) {
|
if (script->hasNonSyntacticScope()) {
|
||||||
lexicalEnv = &NearestEnclosingExtensibleLexicalEnvironment(envChain);
|
lexicalEnv = &NearestEnclosingExtensibleLexicalEnvironment(envChain);
|
||||||
varObj = &GetVariablesObject(envChain);
|
|
||||||
} else {
|
} else {
|
||||||
lexicalEnv = &cx->global()->lexicalEnvironment();
|
lexicalEnv = &cx->global()->lexicalEnvironment();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
RootedObject varObj(cx);
|
||||||
|
if (script->hasNonSyntacticScope()) {
|
||||||
|
varObj = &GetVariablesObject(envChain);
|
||||||
|
} else {
|
||||||
varObj = cx->global();
|
varObj = cx->global();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4658,7 +4650,14 @@ bool js::DefLexicalOperation(JSContext* cx, HandleObject envChain,
|
||||||
lexicalEnv == &cx->global()->lexicalEnvironment() &&
|
lexicalEnv == &cx->global()->lexicalEnvironment() &&
|
||||||
varObj == cx->global());
|
varObj == cx->global());
|
||||||
|
|
||||||
return DefLexicalOperation(cx, lexicalEnv, varObj, name, attrs);
|
// 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,
|
bool js::DefFunOperation(JSContext* cx, HandleScript script,
|
||||||
|
|
|
@ -449,11 +449,6 @@ JSObject* BindVarOperation(JSContext* cx, JSObject* envChain);
|
||||||
bool DefVarOperation(JSContext* cx, HandleObject envChain, HandleScript script,
|
bool DefVarOperation(JSContext* cx, HandleObject envChain, HandleScript script,
|
||||||
jsbytecode* pc);
|
jsbytecode* pc);
|
||||||
|
|
||||||
bool DefLexicalOperation(JSContext* cx,
|
|
||||||
Handle<LexicalEnvironmentObject*> lexicalEnv,
|
|
||||||
HandleObject varObj, HandlePropertyName name,
|
|
||||||
unsigned attrs);
|
|
||||||
|
|
||||||
bool DefLexicalOperation(JSContext* cx, HandleObject envChain,
|
bool DefLexicalOperation(JSContext* cx, HandleObject envChain,
|
||||||
HandleScript script, jsbytecode* pc);
|
HandleScript script, jsbytecode* pc);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче