зеркало из https://github.com/mozilla/gecko-dev.git
Bug 882736 - Ion-compile scripts that use ES5 getter/setter syntax. r=bhackett
This commit is contained in:
Родитель
f558a92953
Коммит
7a271ed06a
|
@ -1991,7 +1991,7 @@ BaselineCompiler::emit_JSOP_DEFFUN()
|
|||
}
|
||||
|
||||
typedef bool (*InitPropGetterSetterFn)(JSContext *, jsbytecode *, HandleObject, HandlePropertyName,
|
||||
HandleValue);
|
||||
HandleObject);
|
||||
static const VMFunction InitPropGetterSetterInfo =
|
||||
FunctionInfo<InitPropGetterSetterFn>(InitGetterSetterOperation);
|
||||
|
||||
|
@ -2001,16 +2001,17 @@ BaselineCompiler::emitInitPropGetterSetter()
|
|||
JS_ASSERT(JSOp(*pc) == JSOP_INITPROP_GETTER ||
|
||||
JSOp(*pc) == JSOP_INITPROP_SETTER);
|
||||
|
||||
// Load value in R0 but keep it on the stack for the decompiler.
|
||||
// Keep values on the stack for the decompiler.
|
||||
frame.syncStack(0);
|
||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushArg(R0);
|
||||
pushArg(ImmGCPtr(script->getName(pc)));
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-2)), R0.scratchReg());
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-2)), R1.scratchReg());
|
||||
|
||||
pushArg(R0.scratchReg());
|
||||
pushArg(ImmGCPtr(script->getName(pc)));
|
||||
pushArg(R1.scratchReg());
|
||||
pushArg(ImmWord(pc));
|
||||
|
||||
if (!callVM(InitPropGetterSetterInfo))
|
||||
|
@ -2033,7 +2034,7 @@ BaselineCompiler::emit_JSOP_INITPROP_SETTER()
|
|||
}
|
||||
|
||||
typedef bool (*InitElemGetterSetterFn)(JSContext *, jsbytecode *, HandleObject, HandleValue,
|
||||
HandleValue);
|
||||
HandleObject);
|
||||
static const VMFunction InitElemGetterSetterInfo =
|
||||
FunctionInfo<InitElemGetterSetterFn>(InitGetterSetterOperation);
|
||||
|
||||
|
@ -2047,11 +2048,11 @@ BaselineCompiler::emitInitElemGetterSetter()
|
|||
// decompiler.
|
||||
frame.syncStack(0);
|
||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
|
||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-1)), R1.scratchReg());
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushArg(R1);
|
||||
pushArg(R1.scratchReg());
|
||||
pushArg(R0);
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-3)), R0.scratchReg());
|
||||
pushArg(R0.scratchReg());
|
||||
|
|
|
@ -3172,6 +3172,25 @@ CodeGenerator::visitInitElem(LInitElem *lir)
|
|||
return callVM(InitElemInfo, lir);
|
||||
}
|
||||
|
||||
typedef bool (*InitElemGetterSetterFn)(JSContext *, jsbytecode *, HandleObject, HandleValue,
|
||||
HandleObject);
|
||||
static const VMFunction InitElemGetterSetterInfo =
|
||||
FunctionInfo<InitElemGetterSetterFn>(InitGetterSetterOperation);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitInitElemGetterSetter(LInitElemGetterSetter *lir)
|
||||
{
|
||||
Register obj = ToRegister(lir->object());
|
||||
Register value = ToRegister(lir->value());
|
||||
|
||||
pushArg(value);
|
||||
pushArg(ToValue(lir, LInitElemGetterSetter::IdIndex));
|
||||
pushArg(obj);
|
||||
pushArg(ImmWord(lir->mir()->resumePoint()->pc()));
|
||||
|
||||
return callVM(InitElemGetterSetterInfo, lir);
|
||||
}
|
||||
|
||||
typedef bool(*InitPropFn)(JSContext *cx, HandleObject obj,
|
||||
HandlePropertyName name, HandleValue value);
|
||||
static const VMFunction InitPropInfo =
|
||||
|
@ -3189,6 +3208,25 @@ CodeGenerator::visitInitProp(LInitProp *lir)
|
|||
return callVM(InitPropInfo, lir);
|
||||
}
|
||||
|
||||
typedef bool(*InitPropGetterSetterFn)(JSContext *, jsbytecode *, HandleObject, HandlePropertyName,
|
||||
HandleObject);
|
||||
static const VMFunction InitPropGetterSetterInfo =
|
||||
FunctionInfo<InitPropGetterSetterFn>(InitGetterSetterOperation);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitInitPropGetterSetter(LInitPropGetterSetter *lir)
|
||||
{
|
||||
Register obj = ToRegister(lir->object());
|
||||
Register value = ToRegister(lir->value());
|
||||
|
||||
pushArg(value);
|
||||
pushArg(ImmGCPtr(lir->mir()->name()));
|
||||
pushArg(obj);
|
||||
pushArg(ImmWord(lir->mir()->resumePoint()->pc()));
|
||||
|
||||
return callVM(InitPropGetterSetterInfo, lir);
|
||||
}
|
||||
|
||||
typedef bool (*CreateThisFn)(JSContext *cx, HandleObject callee, MutableHandleValue rval);
|
||||
static const VMFunction CreateThisInfo = FunctionInfo<CreateThisFn>(CreateThis);
|
||||
|
||||
|
|
|
@ -127,7 +127,9 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitNewDenseArrayPar(LNewDenseArrayPar *lir);
|
||||
bool visitAbortPar(LAbortPar *lir);
|
||||
bool visitInitElem(LInitElem *lir);
|
||||
bool visitInitElemGetterSetter(LInitElemGetterSetter *lir);
|
||||
bool visitInitProp(LInitProp *lir);
|
||||
bool visitInitPropGetterSetter(LInitPropGetterSetter *lir);
|
||||
bool visitCreateThis(LCreateThis *lir);
|
||||
bool visitCreateThisWithProto(LCreateThisWithProto *lir);
|
||||
bool visitCreateThisWithTemplate(LCreateThisWithTemplate *lir);
|
||||
|
|
|
@ -1339,6 +1339,16 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
return jsop_initprop(name);
|
||||
}
|
||||
|
||||
case JSOP_INITPROP_GETTER:
|
||||
case JSOP_INITPROP_SETTER: {
|
||||
PropertyName *name = info().getAtom(pc)->asPropertyName();
|
||||
return jsop_initprop_getter_setter(name);
|
||||
}
|
||||
|
||||
case JSOP_INITELEM_GETTER:
|
||||
case JSOP_INITELEM_SETTER:
|
||||
return jsop_initelem_getter_setter();
|
||||
|
||||
case JSOP_ENDINIT:
|
||||
return true;
|
||||
|
||||
|
@ -5444,6 +5454,29 @@ IonBuilder::jsop_initprop(HandlePropertyName name)
|
|||
return resumeAfter(store);
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_initprop_getter_setter(PropertyName *name)
|
||||
{
|
||||
MDefinition *value = current->pop();
|
||||
MDefinition *obj = current->peek(-1);
|
||||
|
||||
MInitPropGetterSetter *init = MInitPropGetterSetter::New(obj, name, value);
|
||||
current->add(init);
|
||||
return resumeAfter(init);
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_initelem_getter_setter()
|
||||
{
|
||||
MDefinition *value = current->pop();
|
||||
MDefinition *id = current->pop();
|
||||
MDefinition *obj = current->peek(-1);
|
||||
|
||||
MInitElemGetterSetter *init = MInitElemGetterSetter::New(obj, id, value);
|
||||
current->add(init);
|
||||
return resumeAfter(init);
|
||||
}
|
||||
|
||||
MBasicBlock *
|
||||
IonBuilder::addBlock(MBasicBlock *block, uint32_t loopDepth)
|
||||
{
|
||||
|
|
|
@ -422,7 +422,9 @@ class IonBuilder : public MIRGenerator
|
|||
bool jsop_newobject(HandleObject baseObj);
|
||||
bool jsop_initelem();
|
||||
bool jsop_initelem_array();
|
||||
bool jsop_initelem_getter_setter();
|
||||
bool jsop_initprop(HandlePropertyName name);
|
||||
bool jsop_initprop_getter_setter(PropertyName *name);
|
||||
bool jsop_regexp(RegExpObject *reobj);
|
||||
bool jsop_object(JSObject *obj);
|
||||
bool jsop_lambda(JSFunction *fun);
|
||||
|
|
|
@ -530,6 +530,29 @@ class LInitElem : public LCallInstructionHelper<0, 1 + 2*BOX_PIECES, 0>
|
|||
}
|
||||
};
|
||||
|
||||
class LInitElemGetterSetter : public LCallInstructionHelper<0, 2 + BOX_PIECES, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(InitElemGetterSetter)
|
||||
|
||||
LInitElemGetterSetter(const LAllocation &object, const LAllocation &value) {
|
||||
setOperand(0, object);
|
||||
setOperand(1, value);
|
||||
}
|
||||
|
||||
static const size_t IdIndex = 2;
|
||||
|
||||
const LAllocation *object() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LAllocation *value() {
|
||||
return getOperand(1);
|
||||
}
|
||||
MInitElemGetterSetter *mir() const {
|
||||
return mir_->toInitElemGetterSetter();
|
||||
}
|
||||
};
|
||||
|
||||
// Takes in an Object and a Value.
|
||||
class LInitProp : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
|
||||
{
|
||||
|
@ -554,6 +577,28 @@ class LInitProp : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
|
|||
}
|
||||
};
|
||||
|
||||
class LInitPropGetterSetter : public LCallInstructionHelper<0, 2, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(InitPropGetterSetter)
|
||||
|
||||
LInitPropGetterSetter(const LAllocation &object, const LAllocation &value) {
|
||||
setOperand(0, object);
|
||||
setOperand(1, value);
|
||||
}
|
||||
|
||||
const LAllocation *object() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LAllocation *value() {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
MInitPropGetterSetter *mir() const {
|
||||
return mir_->toInitPropGetterSetter();
|
||||
}
|
||||
};
|
||||
|
||||
class LCheckOverRecursed : public LInstructionHelper<0, 0, 0>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -33,7 +33,9 @@
|
|||
_(NewCallObjectPar) \
|
||||
_(AbortPar) \
|
||||
_(InitElem) \
|
||||
_(InitElemGetterSetter) \
|
||||
_(InitProp) \
|
||||
_(InitPropGetterSetter) \
|
||||
_(CheckOverRecursed) \
|
||||
_(CheckOverRecursedPar) \
|
||||
_(DefVar) \
|
||||
|
|
|
@ -252,6 +252,17 @@ LIRGenerator::visitInitElem(MInitElem *ins)
|
|||
return add(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitInitElemGetterSetter(MInitElemGetterSetter *ins)
|
||||
{
|
||||
LInitElemGetterSetter *lir = new LInitElemGetterSetter(useRegisterAtStart(ins->object()),
|
||||
useRegisterAtStart(ins->value()));
|
||||
if (!useBoxAtStart(lir, LInitElemGetterSetter::IdIndex, ins->idValue()))
|
||||
return false;
|
||||
|
||||
return add(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitInitProp(MInitProp *ins)
|
||||
{
|
||||
|
@ -262,6 +273,14 @@ LIRGenerator::visitInitProp(MInitProp *ins)
|
|||
return add(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitInitPropGetterSetter(MInitPropGetterSetter *ins)
|
||||
{
|
||||
LInitPropGetterSetter *lir = new LInitPropGetterSetter(useRegisterAtStart(ins->object()),
|
||||
useRegisterAtStart(ins->value()));
|
||||
return add(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitPrepareCall(MPrepareCall *ins)
|
||||
{
|
||||
|
|
|
@ -94,7 +94,9 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
bool visitNewDenseArrayPar(MNewDenseArrayPar *ins);
|
||||
bool visitAbortPar(MAbortPar *ins);
|
||||
bool visitInitElem(MInitElem *ins);
|
||||
bool visitInitElemGetterSetter(MInitElemGetterSetter *ins);
|
||||
bool visitInitProp(MInitProp *ins);
|
||||
bool visitInitPropGetterSetter(MInitPropGetterSetter *ins);
|
||||
bool visitCheckOverRecursed(MCheckOverRecursed *ins);
|
||||
bool visitCheckOverRecursedPar(MCheckOverRecursedPar *ins);
|
||||
bool visitDefVar(MDefVar *ins);
|
||||
|
|
397
js/src/ion/MIR.h
397
js/src/ion/MIR.h
|
@ -681,6 +681,174 @@ class MUnaryInstruction : public MAryInstruction<1>
|
|||
}
|
||||
};
|
||||
|
||||
class MBinaryInstruction : public MAryInstruction<2>
|
||||
{
|
||||
protected:
|
||||
MBinaryInstruction(MDefinition *left, MDefinition *right)
|
||||
{
|
||||
setOperand(0, left);
|
||||
setOperand(1, right);
|
||||
}
|
||||
|
||||
public:
|
||||
MDefinition *lhs() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
MDefinition *rhs() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
protected:
|
||||
HashNumber valueHash() const
|
||||
{
|
||||
MDefinition *lhs = getOperand(0);
|
||||
MDefinition *rhs = getOperand(1);
|
||||
|
||||
return op() ^ lhs->valueNumber() ^ rhs->valueNumber();
|
||||
}
|
||||
void swapOperands() {
|
||||
MDefinition *temp = getOperand(0);
|
||||
replaceOperand(0, getOperand(1));
|
||||
replaceOperand(1, temp);
|
||||
}
|
||||
|
||||
bool congruentTo(MDefinition *const &ins) const
|
||||
{
|
||||
if (op() != ins->op())
|
||||
return false;
|
||||
|
||||
if (type() != ins->type())
|
||||
return false;
|
||||
|
||||
if (isEffectful() || ins->isEffectful())
|
||||
return false;
|
||||
|
||||
MDefinition *left = getOperand(0);
|
||||
MDefinition *right = getOperand(1);
|
||||
MDefinition *tmp;
|
||||
|
||||
if (isCommutative() && left->valueNumber() > right->valueNumber()) {
|
||||
tmp = right;
|
||||
right = left;
|
||||
left = tmp;
|
||||
}
|
||||
|
||||
MBinaryInstruction *bi = static_cast<MBinaryInstruction *>(ins);
|
||||
MDefinition *insLeft = bi->getOperand(0);
|
||||
MDefinition *insRight = bi->getOperand(1);
|
||||
if (isCommutative() && insLeft->valueNumber() > insRight->valueNumber()) {
|
||||
tmp = insRight;
|
||||
insRight = insLeft;
|
||||
insLeft = tmp;
|
||||
}
|
||||
|
||||
return (left->valueNumber() == insLeft->valueNumber()) &&
|
||||
(right->valueNumber() == insRight->valueNumber());
|
||||
}
|
||||
|
||||
// Return true if the operands to this instruction are both unsigned,
|
||||
// in which case any wrapping operands were replaced with the underlying
|
||||
// int32 operands.
|
||||
bool tryUseUnsignedOperands();
|
||||
};
|
||||
|
||||
class MTernaryInstruction : public MAryInstruction<3>
|
||||
{
|
||||
protected:
|
||||
MTernaryInstruction(MDefinition *first, MDefinition *second, MDefinition *third)
|
||||
{
|
||||
setOperand(0, first);
|
||||
setOperand(1, second);
|
||||
setOperand(2, third);
|
||||
}
|
||||
|
||||
protected:
|
||||
HashNumber valueHash() const
|
||||
{
|
||||
MDefinition *first = getOperand(0);
|
||||
MDefinition *second = getOperand(1);
|
||||
MDefinition *third = getOperand(2);
|
||||
|
||||
return op() ^ first->valueNumber() ^ second->valueNumber() ^ third->valueNumber();
|
||||
}
|
||||
|
||||
bool congruentTo(MDefinition *const &ins) const
|
||||
{
|
||||
if (op() != ins->op())
|
||||
return false;
|
||||
|
||||
if (type() != ins->type())
|
||||
return false;
|
||||
|
||||
if (isEffectful() || ins->isEffectful())
|
||||
return false;
|
||||
|
||||
MTernaryInstruction *ter = static_cast<MTernaryInstruction *>(ins);
|
||||
MDefinition *first = getOperand(0);
|
||||
MDefinition *second = getOperand(1);
|
||||
MDefinition *third = getOperand(2);
|
||||
MDefinition *insFirst = ter->getOperand(0);
|
||||
MDefinition *insSecond = ter->getOperand(1);
|
||||
MDefinition *insThird = ter->getOperand(2);
|
||||
|
||||
return first->valueNumber() == insFirst->valueNumber() &&
|
||||
second->valueNumber() == insSecond->valueNumber() &&
|
||||
third->valueNumber() == insThird->valueNumber();
|
||||
}
|
||||
};
|
||||
|
||||
class MQuaternaryInstruction : public MAryInstruction<4>
|
||||
{
|
||||
protected:
|
||||
MQuaternaryInstruction(MDefinition *first, MDefinition *second,
|
||||
MDefinition *third, MDefinition *fourth)
|
||||
{
|
||||
setOperand(0, first);
|
||||
setOperand(1, second);
|
||||
setOperand(2, third);
|
||||
setOperand(3, fourth);
|
||||
}
|
||||
|
||||
protected:
|
||||
HashNumber valueHash() const
|
||||
{
|
||||
MDefinition *first = getOperand(0);
|
||||
MDefinition *second = getOperand(1);
|
||||
MDefinition *third = getOperand(2);
|
||||
MDefinition *fourth = getOperand(3);
|
||||
|
||||
return op() ^ first->valueNumber() ^ second->valueNumber() ^
|
||||
third->valueNumber() ^ fourth->valueNumber();
|
||||
}
|
||||
|
||||
bool congruentTo(MDefinition *const &ins) const
|
||||
{
|
||||
if (op() != ins->op())
|
||||
return false;
|
||||
|
||||
if (type() != ins->type())
|
||||
return false;
|
||||
|
||||
if (isEffectful() || ins->isEffectful())
|
||||
return false;
|
||||
|
||||
MQuaternaryInstruction *qua = static_cast<MQuaternaryInstruction *>(ins);
|
||||
MDefinition *first = getOperand(0);
|
||||
MDefinition *second = getOperand(1);
|
||||
MDefinition *third = getOperand(2);
|
||||
MDefinition *fourth = getOperand(3);
|
||||
MDefinition *insFirst = qua->getOperand(0);
|
||||
MDefinition *insSecond = qua->getOperand(1);
|
||||
MDefinition *insThird = qua->getOperand(2);
|
||||
MDefinition *insFourth = qua->getOperand(3);
|
||||
|
||||
return first->valueNumber() == insFirst->valueNumber() &&
|
||||
second->valueNumber() == insSecond->valueNumber() &&
|
||||
third->valueNumber() == insThird->valueNumber() &&
|
||||
fourth->valueNumber() == insFourth->valueNumber();
|
||||
}
|
||||
};
|
||||
|
||||
// Generates an LSnapshot without further effect.
|
||||
class MStart : public MNullaryInstruction
|
||||
{
|
||||
|
@ -1327,6 +1495,38 @@ class MInitProp
|
|||
}
|
||||
};
|
||||
|
||||
class MInitPropGetterSetter
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1> >
|
||||
{
|
||||
CompilerRootPropertyName name_;
|
||||
|
||||
MInitPropGetterSetter(MDefinition *obj, PropertyName *name, MDefinition *value)
|
||||
: MBinaryInstruction(obj, value),
|
||||
name_(name)
|
||||
{ }
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(InitPropGetterSetter)
|
||||
|
||||
static MInitPropGetterSetter *New(MDefinition *obj, PropertyName *name, MDefinition *value) {
|
||||
return new MInitPropGetterSetter(obj, name, value);
|
||||
}
|
||||
|
||||
MDefinition *object() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
MDefinition *value() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
PropertyName *name() const {
|
||||
return name_;
|
||||
}
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
class MInitElem
|
||||
: public MAryInstruction<3>,
|
||||
public Mix3Policy<ObjectPolicy<0>, BoxPolicy<1>, BoxPolicy<2> >
|
||||
|
@ -1363,6 +1563,35 @@ class MInitElem
|
|||
}
|
||||
};
|
||||
|
||||
class MInitElemGetterSetter
|
||||
: public MTernaryInstruction,
|
||||
public Mix3Policy<ObjectPolicy<0>, BoxPolicy<1>, ObjectPolicy<2> >
|
||||
{
|
||||
MInitElemGetterSetter(MDefinition *obj, MDefinition *id, MDefinition *value)
|
||||
: MTernaryInstruction(obj, id, value)
|
||||
{ }
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(InitElemGetterSetter)
|
||||
|
||||
static MInitElemGetterSetter *New(MDefinition *obj, MDefinition *id, MDefinition *value) {
|
||||
return new MInitElemGetterSetter(obj, id, value);
|
||||
}
|
||||
|
||||
MDefinition *object() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
MDefinition *idValue() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
MDefinition *value() const {
|
||||
return getOperand(2);
|
||||
}
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
// Designates the start of call frame construction.
|
||||
// Generates code to adjust the stack pointer for the argument vector.
|
||||
// Argc is inferred by checking the use chain during lowering.
|
||||
|
@ -1685,174 +1914,6 @@ class MCallDirectEval
|
|||
jsbytecode *pc_;
|
||||
};
|
||||
|
||||
class MBinaryInstruction : public MAryInstruction<2>
|
||||
{
|
||||
protected:
|
||||
MBinaryInstruction(MDefinition *left, MDefinition *right)
|
||||
{
|
||||
setOperand(0, left);
|
||||
setOperand(1, right);
|
||||
}
|
||||
|
||||
public:
|
||||
MDefinition *lhs() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
MDefinition *rhs() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
protected:
|
||||
HashNumber valueHash() const
|
||||
{
|
||||
MDefinition *lhs = getOperand(0);
|
||||
MDefinition *rhs = getOperand(1);
|
||||
|
||||
return op() ^ lhs->valueNumber() ^ rhs->valueNumber();
|
||||
}
|
||||
void swapOperands() {
|
||||
MDefinition *temp = getOperand(0);
|
||||
replaceOperand(0, getOperand(1));
|
||||
replaceOperand(1, temp);
|
||||
}
|
||||
|
||||
bool congruentTo(MDefinition *const &ins) const
|
||||
{
|
||||
if (op() != ins->op())
|
||||
return false;
|
||||
|
||||
if (type() != ins->type())
|
||||
return false;
|
||||
|
||||
if (isEffectful() || ins->isEffectful())
|
||||
return false;
|
||||
|
||||
MDefinition *left = getOperand(0);
|
||||
MDefinition *right = getOperand(1);
|
||||
MDefinition *tmp;
|
||||
|
||||
if (isCommutative() && left->valueNumber() > right->valueNumber()) {
|
||||
tmp = right;
|
||||
right = left;
|
||||
left = tmp;
|
||||
}
|
||||
|
||||
MBinaryInstruction *bi = static_cast<MBinaryInstruction *>(ins);
|
||||
MDefinition *insLeft = bi->getOperand(0);
|
||||
MDefinition *insRight = bi->getOperand(1);
|
||||
if (isCommutative() && insLeft->valueNumber() > insRight->valueNumber()) {
|
||||
tmp = insRight;
|
||||
insRight = insLeft;
|
||||
insLeft = tmp;
|
||||
}
|
||||
|
||||
return (left->valueNumber() == insLeft->valueNumber()) &&
|
||||
(right->valueNumber() == insRight->valueNumber());
|
||||
}
|
||||
|
||||
// Return true if the operands to this instruction are both unsigned,
|
||||
// in which case any wrapping operands were replaced with the underlying
|
||||
// int32 operands.
|
||||
bool tryUseUnsignedOperands();
|
||||
};
|
||||
|
||||
class MTernaryInstruction : public MAryInstruction<3>
|
||||
{
|
||||
protected:
|
||||
MTernaryInstruction(MDefinition *first, MDefinition *second, MDefinition *third)
|
||||
{
|
||||
setOperand(0, first);
|
||||
setOperand(1, second);
|
||||
setOperand(2, third);
|
||||
}
|
||||
|
||||
protected:
|
||||
HashNumber valueHash() const
|
||||
{
|
||||
MDefinition *first = getOperand(0);
|
||||
MDefinition *second = getOperand(1);
|
||||
MDefinition *third = getOperand(2);
|
||||
|
||||
return op() ^ first->valueNumber() ^ second->valueNumber() ^ third->valueNumber();
|
||||
}
|
||||
|
||||
bool congruentTo(MDefinition *const &ins) const
|
||||
{
|
||||
if (op() != ins->op())
|
||||
return false;
|
||||
|
||||
if (type() != ins->type())
|
||||
return false;
|
||||
|
||||
if (isEffectful() || ins->isEffectful())
|
||||
return false;
|
||||
|
||||
MTernaryInstruction *ter = static_cast<MTernaryInstruction *>(ins);
|
||||
MDefinition *first = getOperand(0);
|
||||
MDefinition *second = getOperand(1);
|
||||
MDefinition *third = getOperand(2);
|
||||
MDefinition *insFirst = ter->getOperand(0);
|
||||
MDefinition *insSecond = ter->getOperand(1);
|
||||
MDefinition *insThird = ter->getOperand(2);
|
||||
|
||||
return first->valueNumber() == insFirst->valueNumber() &&
|
||||
second->valueNumber() == insSecond->valueNumber() &&
|
||||
third->valueNumber() == insThird->valueNumber();
|
||||
}
|
||||
};
|
||||
|
||||
class MQuaternaryInstruction : public MAryInstruction<4>
|
||||
{
|
||||
protected:
|
||||
MQuaternaryInstruction(MDefinition *first, MDefinition *second,
|
||||
MDefinition *third, MDefinition *fourth)
|
||||
{
|
||||
setOperand(0, first);
|
||||
setOperand(1, second);
|
||||
setOperand(2, third);
|
||||
setOperand(3, fourth);
|
||||
}
|
||||
|
||||
protected:
|
||||
HashNumber valueHash() const
|
||||
{
|
||||
MDefinition *first = getOperand(0);
|
||||
MDefinition *second = getOperand(1);
|
||||
MDefinition *third = getOperand(2);
|
||||
MDefinition *fourth = getOperand(3);
|
||||
|
||||
return op() ^ first->valueNumber() ^ second->valueNumber() ^
|
||||
third->valueNumber() ^ fourth->valueNumber();
|
||||
}
|
||||
|
||||
bool congruentTo(MDefinition *const &ins) const
|
||||
{
|
||||
if (op() != ins->op())
|
||||
return false;
|
||||
|
||||
if (type() != ins->type())
|
||||
return false;
|
||||
|
||||
if (isEffectful() || ins->isEffectful())
|
||||
return false;
|
||||
|
||||
MQuaternaryInstruction *qua = static_cast<MQuaternaryInstruction *>(ins);
|
||||
MDefinition *first = getOperand(0);
|
||||
MDefinition *second = getOperand(1);
|
||||
MDefinition *third = getOperand(2);
|
||||
MDefinition *fourth = getOperand(3);
|
||||
MDefinition *insFirst = qua->getOperand(0);
|
||||
MDefinition *insSecond = qua->getOperand(1);
|
||||
MDefinition *insThird = qua->getOperand(2);
|
||||
MDefinition *insFourth = qua->getOperand(3);
|
||||
|
||||
return first->valueNumber() == insFirst->valueNumber() &&
|
||||
second->valueNumber() == insSecond->valueNumber() &&
|
||||
third->valueNumber() == insThird->valueNumber() &&
|
||||
fourth->valueNumber() == insFourth->valueNumber();
|
||||
}
|
||||
};
|
||||
|
||||
class MCompare
|
||||
: public MBinaryInstruction,
|
||||
public ComparePolicy
|
||||
|
|
|
@ -86,7 +86,9 @@ namespace ion {
|
|||
_(NewCallObject) \
|
||||
_(NewStringObject) \
|
||||
_(InitElem) \
|
||||
_(InitElemGetterSetter) \
|
||||
_(InitProp) \
|
||||
_(InitPropGetterSetter) \
|
||||
_(Start) \
|
||||
_(OsrEntry) \
|
||||
_(Nop) \
|
||||
|
|
|
@ -175,7 +175,9 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
|||
CUSTOM_OP(NewCallObject)
|
||||
CUSTOM_OP(NewParallelArray)
|
||||
UNSAFE_OP(InitElem)
|
||||
UNSAFE_OP(InitElemGetterSetter)
|
||||
UNSAFE_OP(InitProp)
|
||||
UNSAFE_OP(InitPropGetterSetter)
|
||||
SAFE_OP(Start)
|
||||
UNSAFE_OP(OsrEntry)
|
||||
SAFE_OP(Nop)
|
||||
|
|
|
@ -2915,12 +2915,12 @@ BEGIN_CASE(JSOP_INITPROP_SETTER)
|
|||
{
|
||||
RootedObject &obj = rootObject0;
|
||||
RootedPropertyName &name = rootName0;
|
||||
RootedValue &val = rootValue0;
|
||||
RootedObject &val = rootObject1;
|
||||
|
||||
JS_ASSERT(regs.stackDepth() >= 2);
|
||||
obj = ®s.sp[-2].toObject();
|
||||
name = script->getName(regs.pc);
|
||||
val = regs.sp[-1];
|
||||
val = ®s.sp[-1].toObject();
|
||||
|
||||
if (!InitGetterSetterOperation(cx, regs.pc, obj, name, val))
|
||||
goto error;
|
||||
|
@ -2934,12 +2934,12 @@ BEGIN_CASE(JSOP_INITELEM_SETTER)
|
|||
{
|
||||
RootedObject &obj = rootObject0;
|
||||
RootedValue &idval = rootValue0;
|
||||
RootedValue &val = rootValue1;
|
||||
RootedObject &val = rootObject1;
|
||||
|
||||
JS_ASSERT(regs.stackDepth() >= 3);
|
||||
obj = ®s.sp[-3].toObject();
|
||||
idval = regs.sp[-2];
|
||||
val = regs.sp[-1];
|
||||
val = ®s.sp[-1].toObject();
|
||||
|
||||
if (!InitGetterSetterOperation(cx, regs.pc, obj, idval, val))
|
||||
goto error;
|
||||
|
@ -3860,9 +3860,9 @@ js::RunOnceScriptPrologue(JSContext *cx, HandleScript script)
|
|||
|
||||
bool
|
||||
js::InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandleId id,
|
||||
HandleValue val)
|
||||
HandleObject val)
|
||||
{
|
||||
JS_ASSERT(js_IsCallable(val));
|
||||
JS_ASSERT(val->isCallable());
|
||||
|
||||
/*
|
||||
* Getters and setters are just like watchpoints from an access control
|
||||
|
@ -3880,13 +3880,13 @@ js::InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, H
|
|||
JSOp op = JSOp(*pc);
|
||||
|
||||
if (op == JSOP_INITPROP_GETTER || op == JSOP_INITELEM_GETTER) {
|
||||
getter = CastAsPropertyOp(&val.toObject());
|
||||
getter = CastAsPropertyOp(val);
|
||||
setter = JS_StrictPropertyStub;
|
||||
attrs |= JSPROP_GETTER;
|
||||
} else {
|
||||
JS_ASSERT(op == JSOP_INITPROP_SETTER || op == JSOP_INITELEM_SETTER);
|
||||
getter = JS_PropertyStub;
|
||||
setter = CastAsStrictPropertyOp(&val.toObject());
|
||||
setter = CastAsStrictPropertyOp(val);
|
||||
attrs |= JSPROP_SETTER;
|
||||
}
|
||||
|
||||
|
@ -3896,7 +3896,7 @@ js::InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, H
|
|||
|
||||
bool
|
||||
js::InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj,
|
||||
HandlePropertyName name, HandleValue val)
|
||||
HandlePropertyName name, HandleObject val)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return InitGetterSetterOperation(cx, pc, obj, id, val);
|
||||
|
@ -3904,7 +3904,7 @@ js::InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj,
|
|||
|
||||
bool
|
||||
js::InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandleValue idval,
|
||||
HandleValue val)
|
||||
HandleObject val)
|
||||
{
|
||||
RootedId id(cx);
|
||||
if (!ValueToId<CanGC>(cx, idval, &id))
|
||||
|
|
|
@ -499,15 +499,15 @@ RunOnceScriptPrologue(JSContext *cx, HandleScript script);
|
|||
|
||||
bool
|
||||
InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandleId id,
|
||||
HandleValue val);
|
||||
HandleObject val);
|
||||
|
||||
bool
|
||||
InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandlePropertyName name,
|
||||
HandleValue val);
|
||||
HandleObject val);
|
||||
|
||||
bool
|
||||
InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandleValue idval,
|
||||
HandleValue val);
|
||||
HandleObject val);
|
||||
|
||||
inline bool
|
||||
SetConstOperation(JSContext *cx, HandleObject varobj, HandlePropertyName name, HandleValue rval)
|
||||
|
|
Загрузка…
Ссылка в новой задаче