Bug 814177 - Use a callVM for generic InstanceOf cases. r=dvander

This commit is contained in:
Nicolas B. Pierron 2012-11-26 19:08:37 -08:00
Родитель 4bec908ccc
Коммит 047f75f8d3
12 изменённых файлов: 59 добавлений и 266 удалений

Просмотреть файл

@ -3418,8 +3418,6 @@ class OutOfLineCache : public OutOfLineCodeBase<CodeGenerator>
bool accept(CodeGenerator *codegen) { bool accept(CodeGenerator *codegen) {
switch (ins->op()) { switch (ins->op()) {
case LInstruction::LOp_InstanceOfO:
case LInstruction::LOp_InstanceOfV:
case LInstruction::LOp_GetPropertyCacheT: case LInstruction::LOp_GetPropertyCacheT:
case LInstruction::LOp_GetPropertyCacheV: case LInstruction::LOp_GetPropertyCacheV:
return codegen->visitOutOfLineCacheGetProperty(this); return codegen->visitOutOfLineCacheGetProperty(this);
@ -3531,12 +3529,6 @@ CodeGenerator::visitOutOfLineCacheGetProperty(OutOfLineCache *ool)
PropertyName *name = NULL; PropertyName *name = NULL;
bool allowGetters = false; bool allowGetters = false;
switch (ins->op()) { switch (ins->op()) {
case LInstruction::LOp_InstanceOfO:
case LInstruction::LOp_InstanceOfV:
name = gen->compartment->rt->atomState.classPrototype;
objReg = ToRegister(ins->getTemp(1));
output = TypedOrValueRegister(MIRType_Object, ToAnyRegister(ins->getDef(0)));
break;
case LInstruction::LOp_GetPropertyCacheT: case LInstruction::LOp_GetPropertyCacheT:
name = ((LGetPropertyCacheT *) ins)->mir()->name(); name = ((LGetPropertyCacheT *) ins)->mir()->name();
objReg = ToRegister(ins->getOperand(0)); objReg = ToRegister(ins->getOperand(0));
@ -4214,15 +4206,15 @@ CodeGenerator::visitInArray(LInArray *lir)
} }
bool bool
CodeGenerator::visitInstanceOfTypedO(LInstanceOfTypedO *ins) CodeGenerator::visitInstanceOfO(LInstanceOfO *ins)
{ {
return emitInstanceOfTyped(ins, ins->mir()->prototypeObject()); return emitInstanceOf(ins, ins->mir()->prototypeObject());
} }
bool bool
CodeGenerator::visitInstanceOfTypedV(LInstanceOfTypedV *ins) CodeGenerator::visitInstanceOfV(LInstanceOfV *ins)
{ {
return emitInstanceOfTyped(ins, ins->mir()->prototypeObject()); return emitInstanceOf(ins, ins->mir()->prototypeObject());
} }
// Wrap IsDelegate, which takes a Value for the lhs of an instanceof. // Wrap IsDelegate, which takes a Value for the lhs of an instanceof.
@ -4240,7 +4232,7 @@ typedef bool (*IsDelegateObjectFn)(JSContext *, HandleObject, HandleObject, JSBo
static const VMFunction IsDelegateObjectInfo = FunctionInfo<IsDelegateObjectFn>(IsDelegateObject); static const VMFunction IsDelegateObjectInfo = FunctionInfo<IsDelegateObjectFn>(IsDelegateObject);
bool bool
CodeGenerator::emitInstanceOfTyped(LInstruction *ins, RawObject prototypeObject) CodeGenerator::emitInstanceOf(LInstruction *ins, RawObject prototypeObject)
{ {
// This path implements fun_hasInstance when the function's prototype is // This path implements fun_hasInstance when the function's prototype is
// known to be prototypeObject. // known to be prototypeObject.
@ -4250,16 +4242,16 @@ CodeGenerator::emitInstanceOfTyped(LInstruction *ins, RawObject prototypeObject)
// If the lhs is a primitive, the result is false. // If the lhs is a primitive, the result is false.
Register objReg; Register objReg;
if (ins->isInstanceOfTypedV()) { if (ins->isInstanceOfV()) {
Label isObject; Label isObject;
ValueOperand lhsValue = ToValue(ins, LInstanceOfTypedV::LHS); ValueOperand lhsValue = ToValue(ins, LInstanceOfV::LHS);
masm.branchTestObject(Assembler::Equal, lhsValue, &isObject); masm.branchTestObject(Assembler::Equal, lhsValue, &isObject);
masm.mov(Imm32(0), output); masm.mov(Imm32(0), output);
masm.jump(&done); masm.jump(&done);
masm.bind(&isObject); masm.bind(&isObject);
objReg = masm.extractObject(lhsValue, output); objReg = masm.extractObject(lhsValue, output);
} else { } else {
objReg = ToRegister(ins->toInstanceOfTypedO()->lhs()); objReg = ToRegister(ins->toInstanceOfO()->lhs());
} }
// Crawl the lhs's prototype chain in a loop to search for prototypeObject. // Crawl the lhs's prototype chain in a loop to search for prototypeObject.
@ -4311,11 +4303,11 @@ CodeGenerator::emitInstanceOfTyped(LInstruction *ins, RawObject prototypeObject)
} else { } else {
masm.bind(&regenerate); masm.bind(&regenerate);
lazyEntry = &regenerate; lazyEntry = &regenerate;
if (ins->isInstanceOfTypedV()) { if (ins->isInstanceOfV()) {
ValueOperand lhsValue = ToValue(ins, LInstanceOfTypedV::LHS); ValueOperand lhsValue = ToValue(ins, LInstanceOfV::LHS);
objReg = masm.extractObject(lhsValue, output); objReg = masm.extractObject(lhsValue, output);
} else { } else {
objReg = ToRegister(ins->toInstanceOfTypedO()->lhs()); objReg = ToRegister(ins->toInstanceOfO()->lhs());
} }
JS_ASSERT(objReg == output); JS_ASSERT(objReg == output);
masm.jump(ool->entry()); masm.jump(ool->entry());
@ -4329,182 +4321,19 @@ CodeGenerator::emitInstanceOfTyped(LInstruction *ins, RawObject prototypeObject)
return true; return true;
} }
bool
CodeGenerator::visitInstanceOfO(LInstanceOfO *ins)
{
Register rhs = ToRegister(ins->getOperand(1));
return emitInstanceOf(ins, rhs);
}
bool
CodeGenerator::visitInstanceOfV(LInstanceOfV *ins)
{
Register rhs = ToRegister(ins->getOperand(LInstanceOfV::RHS));
return emitInstanceOf(ins, rhs);
}
typedef bool (*HasInstanceFn)(JSContext *, HandleObject, HandleValue, JSBool *); typedef bool (*HasInstanceFn)(JSContext *, HandleObject, HandleValue, JSBool *);
static const VMFunction HasInstanceInfo = FunctionInfo<HasInstanceFn>(js::HasInstance); static const VMFunction HasInstanceInfo = FunctionInfo<HasInstanceFn>(js::HasInstance);
bool bool
CodeGenerator::emitInstanceOf(LInstruction *ins, Register rhs) CodeGenerator::visitCallInstanceOf(LCallInstanceOf *ins)
{ {
Register rhsTmp = ToRegister(ins->getTemp(1)); ValueOperand lhs = ToValue(ins, LCallInstanceOf::LHS);
Register output = ToRegister(ins->getDef(0)); Register rhs = ToRegister(ins->rhs());
JS_ASSERT(ToRegister(ins->output()) == ReturnReg);
// This temporary is used in other parts of the code. pushArg(lhs);
// Different names are used so the purpose is clear. pushArg(rhs);
Register rhsFlags = ToRegister(ins->getTemp(0)); return callVM(HasInstanceInfo, ins);
Register lhsTmp = ToRegister(ins->getTemp(0));
Label boundFunctionCheck;
Label boundFunctionDone;
Label done;
Label loopPrototypeChain;
JS_ASSERT(ins->isInstanceOfO() || ins->isInstanceOfV());
bool lhsIsValue = ins->isInstanceOfV();
// If the lhs is an object, then the ValueOperand that gets sent to
// HasInstance must be boxed first. If the lhs is a value, it can
// be sent directly. Hence the choice between ToValue and ToTempValue
// below. Note that the same check is done below in the generated code
// and explicit boxing instructions emitted before calling the OOL code
// if we're handling a LInstanceOfO.
OutOfLineCode *call = oolCallVM(HasInstanceInfo, ins,
(ArgList(), rhs, lhsIsValue ? ToValue(ins, 0) : ToTempValue(ins, 0)),
StoreRegisterTo(output));
if (!call)
return false;
// 1. CODE FOR HASINSTANCE_BOUND_FUNCTION
// ASM-equivalent of following code
// boundFunctionCheck:
// if (!rhs->isFunction())
// goto callHasInstance
// if (!rhs->isBoundFunction())
// goto HasInstanceCunction
// rhs = rhs->getBoundFunction();
// goto boundFunctionCheck
masm.mov(rhs, rhsTmp);
// Check Function
masm.bind(&boundFunctionCheck);
masm.loadBaseShape(rhsTmp, output);
masm.cmpPtr(Address(output, BaseShape::offsetOfClass()), ImmWord(&js::FunctionClass));
if (lhsIsValue) {
// If the input LHS is a value, no boxing necessary.
masm.j(Assembler::NotEqual, call->entry());
} else {
// If the input LHS is raw object pointer, it must be boxed before
// calling into js::HasInstance.
Label dontCallHasInstance;
masm.j(Assembler::Equal, &dontCallHasInstance);
masm.boxNonDouble(JSVAL_TYPE_OBJECT, ToRegister(ins->getOperand(0)), ToTempValue(ins, 0));
masm.jump(call->entry());
masm.bind(&dontCallHasInstance);
}
// Check Bound Function
masm.loadPtr(Address(output, BaseShape::offsetOfFlags()), rhsFlags);
masm.and32(Imm32(BaseShape::BOUND_FUNCTION), rhsFlags);
masm.j(Assembler::Zero, &boundFunctionDone);
// Get Bound Function
masm.loadPtr(Address(output, BaseShape::offsetOfParent()), rhsTmp);
masm.jump(&boundFunctionCheck);
// 2. CODE FOR HASINSTANCE_FUNCTION
masm.bind(&boundFunctionDone);
// ASM-equivalent of following code
// if (!lhs->isObject()) {
// output = false;
// goto done;
// }
// rhs = rhs->getPrototypeClass();
// output = false;
// while (1) {
// lhs = lhs->getType().proto;
// if (lhs == NULL)
// goto done;
// if (lhs != rhs) {
// output = true;
// goto done;
// }
// }
// When lhs is a value: The HasInstance for function objects always
// return false when lhs isn't an object. So check if
// lhs is an object and otherwise return false
if (lhsIsValue) {
Label isObject;
ValueOperand lhsValue = ToValue(ins, LInstanceOfV::LHS);
masm.branchTestObject(Assembler::Equal, lhsValue, &isObject);
masm.mov(Imm32(0), output);
masm.jump(&done);
masm.bind(&isObject);
Register tmp = masm.extractObject(lhsValue, lhsTmp);
masm.mov(tmp, lhsTmp);
} else {
masm.mov(ToRegister(ins->getOperand(0)), lhsTmp);
}
// Get prototype-class by using a OutOfLine GetProperty Cache
// It will use register 'rhsTmp' as input and register 'output' as output, see r1889
OutOfLineCache *ool = new OutOfLineCache(ins);
if (!addOutOfLineCode(ool))
return false;
// If the IC code wants to patch, make sure there is enough space to that
// the patching does not overwrite an invalidation marker.
ensureOsiSpace();
CodeOffsetJump jump = masm.jumpWithPatch(ool->repatchEntry());
CodeOffsetLabel label = masm.labelForPatch();
masm.bind(ool->rejoin());
ool->setInlineJump(jump, label);
// Move the OutOfLineCache return value and set the output on false
masm.mov(output, rhsTmp);
masm.mov(Imm32(0), output);
// Walk the prototype chain
masm.bind(&loopPrototypeChain);
masm.loadPtr(Address(lhsTmp, JSObject::offsetOfType()), lhsTmp);
masm.loadPtr(Address(lhsTmp, offsetof(types::TypeObject, proto)), lhsTmp);
// Bail out if we hit a lazy proto
if (lhsIsValue) {
masm.branch32(Assembler::Equal, lhsTmp, Imm32(1), call->entry());
} else {
// If the input LHS is raw object pointer, it must be boxed before
// calling into js::HasInstance.
Label dontCallHasInstance;
masm.branch32(Assembler::NotEqual, lhsTmp, Imm32(1), &dontCallHasInstance);
masm.boxNonDouble(JSVAL_TYPE_OBJECT, ToRegister(ins->getOperand(0)), ToTempValue(ins, 0));
masm.jump(call->entry());
masm.bind(&dontCallHasInstance);
}
masm.testPtr(lhsTmp, lhsTmp);
masm.j(Assembler::Zero, &done);
// Check lhs is equal to rhsShape
masm.cmpPtr(lhsTmp, rhsTmp);
masm.j(Assembler::NotEqual, &loopPrototypeChain);
// return true
masm.mov(Imm32(1), output);
masm.bind(call->rejoin());
masm.bind(&done);
return true;
} }
bool bool

Просмотреть файл

@ -168,14 +168,12 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitCallDeleteProperty(LCallDeleteProperty *lir); bool visitCallDeleteProperty(LCallDeleteProperty *lir);
bool visitBitNotV(LBitNotV *lir); bool visitBitNotV(LBitNotV *lir);
bool visitBitOpV(LBitOpV *lir); bool visitBitOpV(LBitOpV *lir);
bool emitInstanceOfTyped(LInstruction *ins, RawObject prototypeObject); bool emitInstanceOf(LInstruction *ins, RawObject prototypeObject);
bool emitInstanceOf(LInstruction *ins, Register rhs);
bool visitIn(LIn *ins); bool visitIn(LIn *ins);
bool visitInArray(LInArray *ins); bool visitInArray(LInArray *ins);
bool visitInstanceOfTypedO(LInstanceOfTypedO *ins);
bool visitInstanceOfTypedV(LInstanceOfTypedV *ins);
bool visitInstanceOfO(LInstanceOfO *ins); bool visitInstanceOfO(LInstanceOfO *ins);
bool visitInstanceOfV(LInstanceOfV *ins); bool visitInstanceOfV(LInstanceOfV *ins);
bool visitCallInstanceOf(LCallInstanceOf *ins);
bool visitFunctionBoundary(LFunctionBoundary *lir); bool visitFunctionBoundary(LFunctionBoundary *lir);
bool visitGetDOMProperty(LGetDOMProperty *lir); bool visitGetDOMProperty(LGetDOMProperty *lir);
bool visitSetDOMProperty(LSetDOMProperty *lir); bool visitSetDOMProperty(LSetDOMProperty *lir);

Просмотреть файл

@ -6527,7 +6527,7 @@ IonBuilder::jsop_instanceof()
if (!protoObject) if (!protoObject)
break; break;
MInstanceOfTyped *ins = new MInstanceOfTyped(obj, protoObject); MInstanceOf *ins = new MInstanceOf(obj, protoObject);
current->add(ins); current->add(ins);
current->push(ins); current->push(ins);
@ -6535,7 +6535,7 @@ IonBuilder::jsop_instanceof()
return resumeAfter(ins); return resumeAfter(ins);
} while (false); } while (false);
MInstanceOf *ins = new MInstanceOf(obj, rhs); MCallInstanceOf *ins = new MCallInstanceOf(obj, rhs);
current->add(ins); current->add(ins);
current->push(ins); current->push(ins);

Просмотреть файл

@ -1927,4 +1927,3 @@ js::ion::GetNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
return true; return true;
} }

Просмотреть файл

@ -3146,16 +3146,16 @@ class LIn : public LCallInstructionHelper<1, BOX_PIECES+1, 0>
static const size_t RHS = BOX_PIECES; static const size_t RHS = BOX_PIECES;
}; };
class LInstanceOfTypedO : public LInstructionHelper<1, 1, 0> class LInstanceOfO : public LInstructionHelper<1, 1, 0>
{ {
public: public:
LIR_HEADER(InstanceOfTypedO); LIR_HEADER(InstanceOfO);
LInstanceOfTypedO(const LAllocation &lhs) { LInstanceOfO(const LAllocation &lhs) {
setOperand(0, lhs); setOperand(0, lhs);
} }
MInstanceOfTyped *mir() const { MInstanceOf *mir() const {
return mir_->toInstanceOfTyped(); return mir_->toInstanceOf();
} }
const LAllocation *lhs() { const LAllocation *lhs() {
@ -3163,15 +3163,15 @@ class LInstanceOfTypedO : public LInstructionHelper<1, 1, 0>
} }
}; };
class LInstanceOfTypedV : public LInstructionHelper<1, BOX_PIECES, 0> class LInstanceOfV : public LInstructionHelper<1, BOX_PIECES, 0>
{ {
public: public:
LIR_HEADER(InstanceOfTypedV); LIR_HEADER(InstanceOfV);
LInstanceOfTypedV() { LInstanceOfV() {
} }
MInstanceOfTyped *mir() const { MInstanceOf *mir() const {
return mir_->toInstanceOfTyped(); return mir_->toInstanceOf();
} }
const LAllocation *lhs() { const LAllocation *lhs() {
@ -3181,37 +3181,17 @@ class LInstanceOfTypedV : public LInstructionHelper<1, BOX_PIECES, 0>
static const size_t LHS = 0; static const size_t LHS = 0;
}; };
class LInstanceOfO : public LInstructionHelper<1, 2, 2> class LCallInstanceOf : public LCallInstructionHelper<1, BOX_PIECES+1, 0>
{ {
public: public:
LIR_HEADER(InstanceOfO); LIR_HEADER(CallInstanceOf);
LInstanceOfO(const LAllocation &lhs, const LAllocation &rhs, LCallInstanceOf(const LAllocation &rhs) {
const LDefinition &temp, const LDefinition &temp2)
{
setOperand(0, lhs);
setOperand(1, rhs);
setTemp(0, temp);
setTemp(1, temp2);
}
const LAllocation *lhs() {
return getOperand(0);
}
const LAllocation *rhs() {
return getOperand(1);
}
};
class LInstanceOfV : public LInstructionHelper<1, BOX_PIECES+1, 2>
{
public:
LIR_HEADER(InstanceOfV);
LInstanceOfV(const LAllocation &rhs, const LDefinition &temp, const LDefinition &temp2) {
setOperand(RHS, rhs); setOperand(RHS, rhs);
setTemp(0, temp);
setTemp(1, temp2);
} }
const LDefinition *output() {
return this->getDef(0);
}
const LAllocation *lhs() { const LAllocation *lhs() {
return getOperand(LHS); return getOperand(LHS);
} }

Просмотреть файл

@ -169,10 +169,9 @@
_(Round) \ _(Round) \
_(In) \ _(In) \
_(InArray) \ _(InArray) \
_(InstanceOfTypedO) \
_(InstanceOfTypedV) \
_(InstanceOfO) \ _(InstanceOfO) \
_(InstanceOfV) \ _(InstanceOfV) \
_(CallInstanceOf) \
_(InterruptCheck) \ _(InterruptCheck) \
_(FunctionBoundary) \ _(FunctionBoundary) \
_(GetDOMProperty) \ _(GetDOMProperty) \

Просмотреть файл

@ -1925,37 +1925,34 @@ LIRGenerator::visitIn(MIn *ins)
} }
bool bool
LIRGenerator::visitInstanceOfTyped(MInstanceOfTyped *ins) LIRGenerator::visitInstanceOf(MInstanceOf *ins)
{ {
MDefinition *lhs = ins->getOperand(0); MDefinition *lhs = ins->getOperand(0);
JS_ASSERT(lhs->type() == MIRType_Value || lhs->type() == MIRType_Object); JS_ASSERT(lhs->type() == MIRType_Value || lhs->type() == MIRType_Object);
if (lhs->type() == MIRType_Object) { if (lhs->type() == MIRType_Object) {
LInstanceOfTypedO *lir = new LInstanceOfTypedO(useRegister(lhs)); LInstanceOfO *lir = new LInstanceOfO(useRegister(lhs));
return define(lir, ins) && assignSafepoint(lir, ins); return define(lir, ins) && assignSafepoint(lir, ins);
} }
LInstanceOfTypedV *lir = new LInstanceOfTypedV(); LInstanceOfV *lir = new LInstanceOfV();
return useBox(lir, LInstanceOfTypedV::LHS, lhs) && define(lir, ins) && assignSafepoint(lir, ins); return useBox(lir, LInstanceOfV::LHS, lhs) && define(lir, ins) && assignSafepoint(lir, ins);
} }
bool bool
LIRGenerator::visitInstanceOf(MInstanceOf *ins) LIRGenerator::visitCallInstanceOf(MCallInstanceOf *ins)
{ {
MDefinition *lhs = ins->lhs(); MDefinition *lhs = ins->lhs();
MDefinition *rhs = ins->rhs(); MDefinition *rhs = ins->rhs();
JS_ASSERT(lhs->type() == MIRType_Value || lhs->type() == MIRType_Object); JS_ASSERT(lhs->type() == MIRType_Value);
JS_ASSERT(rhs->type() == MIRType_Object); JS_ASSERT(rhs->type() == MIRType_Object);
if (lhs->type() == MIRType_Object) { LCallInstanceOf *lir = new LCallInstanceOf(useRegisterAtStart(rhs));
LInstanceOfO *lir = new LInstanceOfO(useRegister(lhs), useRegister(rhs), temp(), temp()); if (!useBoxAtStart(lir, LCallInstanceOf::LHS, lhs))
return define(lir, ins) && assignSafepoint(lir, ins); return false;
} return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
LInstanceOfV *lir = new LInstanceOfV(useRegister(rhs), temp(), temp());
return useBox(lir, LInstanceOfV::LHS, lhs) && define(lir, ins) && assignSafepoint(lir, ins);
} }
bool bool

Просмотреть файл

@ -184,8 +184,8 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitThrow(MThrow *ins); bool visitThrow(MThrow *ins);
bool visitIn(MIn *ins); bool visitIn(MIn *ins);
bool visitInArray(MInArray *ins); bool visitInArray(MInArray *ins);
bool visitInstanceOfTyped(MInstanceOfTyped *ins);
bool visitInstanceOf(MInstanceOf *ins); bool visitInstanceOf(MInstanceOf *ins);
bool visitCallInstanceOf(MCallInstanceOf *ins);
bool visitFunctionBoundary(MFunctionBoundary *ins); bool visitFunctionBoundary(MFunctionBoundary *ins);
bool visitSetDOMProperty(MSetDOMProperty *ins); bool visitSetDOMProperty(MSetDOMProperty *ins);
bool visitGetDOMProperty(MGetDOMProperty *ins); bool visitGetDOMProperty(MGetDOMProperty *ins);

Просмотреть файл

@ -5246,21 +5246,21 @@ class MInArray
}; };
// Implementation for instanceof operator with specific rhs. // Implementation for instanceof operator with specific rhs.
class MInstanceOfTyped class MInstanceOf
: public MUnaryInstruction, : public MUnaryInstruction,
public InstanceOfPolicy public InstanceOfPolicy
{ {
CompilerRootObject protoObj_; CompilerRootObject protoObj_;
public: public:
MInstanceOfTyped(MDefinition *obj, RawObject proto) MInstanceOf(MDefinition *obj, RawObject proto)
: MUnaryInstruction(obj) : MUnaryInstruction(obj)
{ {
protoObj_ = proto; protoObj_ = proto;
setResultType(MIRType_Boolean); setResultType(MIRType_Boolean);
} }
INSTRUCTION_HEADER(InstanceOfTyped); INSTRUCTION_HEADER(InstanceOf);
TypePolicy *typePolicy() { TypePolicy *typePolicy() {
return this; return this;
@ -5272,18 +5272,18 @@ class MInstanceOfTyped
}; };
// Implementation for instanceof operator with unknown rhs. // Implementation for instanceof operator with unknown rhs.
class MInstanceOf class MCallInstanceOf
: public MBinaryInstruction, : public MBinaryInstruction,
public InstanceOfPolicy public MixPolicy<BoxPolicy<0>, ObjectPolicy<1> >
{ {
public: public:
MInstanceOf(MDefinition *obj, MDefinition *proto) MCallInstanceOf(MDefinition *obj, MDefinition *proto)
: MBinaryInstruction(obj, proto) : MBinaryInstruction(obj, proto)
{ {
setResultType(MIRType_Boolean); setResultType(MIRType_Boolean);
} }
INSTRUCTION_HEADER(InstanceOf); INSTRUCTION_HEADER(CallInstanceOf);
TypePolicy *typePolicy() { TypePolicy *typePolicy() {
return this; return this;

Просмотреть файл

@ -133,8 +133,8 @@ namespace ion {
_(Floor) \ _(Floor) \
_(Round) \ _(Round) \
_(In) \ _(In) \
_(InstanceOfTyped) \
_(InstanceOf) \ _(InstanceOf) \
_(CallInstanceOf) \
_(InterruptCheck) \ _(InterruptCheck) \
_(FunctionBoundary) \ _(FunctionBoundary) \
_(GetDOMProperty) \ _(GetDOMProperty) \

Просмотреть файл

@ -386,12 +386,6 @@ InstanceOfPolicy::adjustInputs(MInstruction *def)
BoxPolicy<0>::staticAdjustInputs(def); BoxPolicy<0>::staticAdjustInputs(def);
} }
if (def->numOperands() == 2) {
// Unbox second operand forcefully to an object,
// so it bailouts with other types
ObjectPolicy<1>::staticAdjustInputs(def);
}
return true; return true;
} }

Просмотреть файл

@ -480,11 +480,8 @@ fun_hasInstance(JSContext *cx, HandleObject objArg, MutableHandleValue v, JSBool
{ {
RootedObject obj(cx, objArg); RootedObject obj(cx, objArg);
while (obj->isFunction()) { while (obj->isFunction() && obj->isBoundFunction())
if (!obj->isBoundFunction())
break;
obj = obj->toFunction()->getBoundFunctionTarget(); obj = obj->toFunction()->getBoundFunctionTarget();
}
RootedValue pval(cx); RootedValue pval(cx);
if (!JSObject::getProperty(cx, obj, obj, cx->names().classPrototype, &pval)) if (!JSObject::getProperty(cx, obj, obj, cx->names().classPrototype, &pval))