зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1021739
- Transform the selfhosting IsObject function into an intrinsic, r=h4writer
This commit is contained in:
Родитель
2711b03876
Коммит
821c5897ee
|
@ -143,22 +143,6 @@ function CheckObjectCoercible(v) {
|
|||
ThrowError(JSMSG_CANT_CONVERT_TO, ToString(v), "object");
|
||||
}
|
||||
|
||||
|
||||
/********** Various utility functions **********/
|
||||
|
||||
|
||||
/** Returns true iff Type(v) is Object; see ES5 8.6. */
|
||||
function IsObject(v) {
|
||||
// Watch out for |typeof null === "object"| as the most obvious pitfall.
|
||||
// But also be careful of SpiderMonkey's objects that emulate undefined
|
||||
// (i.e. |document.all|), which have bogus |typeof| behavior. Detect
|
||||
// these objects using strict equality, which said bogosity doesn't affect.
|
||||
return (typeof v === "object" && v !== null) ||
|
||||
typeof v === "function" ||
|
||||
(typeof v === "undefined" && v !== undefined);
|
||||
}
|
||||
|
||||
|
||||
/********** Testing code **********/
|
||||
|
||||
#ifdef ENABLE_PARALLEL_JS
|
||||
|
|
|
@ -8484,6 +8484,15 @@ CodeGenerator::visitIsCallable(LIsCallable *ins)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitIsObject(LIsObject *ins)
|
||||
{
|
||||
Register output = ToRegister(ins->output());
|
||||
ValueOperand value = ToValue(ins, LIsObject::Input);
|
||||
masm.testObjectSet(Assembler::Equal, value, output);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::loadOutermostJSScript(Register reg)
|
||||
{
|
||||
|
|
|
@ -290,6 +290,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitCallDOMNative(LCallDOMNative *lir);
|
||||
bool visitCallGetIntrinsicValue(LCallGetIntrinsicValue *lir);
|
||||
bool visitIsCallable(LIsCallable *lir);
|
||||
bool visitIsObject(LIsObject *lir);
|
||||
bool visitHaveSameClass(LHaveSameClass *lir);
|
||||
bool visitHasClass(LHasClass *lir);
|
||||
bool visitAsmJSCall(LAsmJSCall *lir);
|
||||
|
|
|
@ -730,6 +730,7 @@ class IonBuilder : public MIRGenerator
|
|||
|
||||
// Utility intrinsics.
|
||||
InliningStatus inlineIsCallable(CallInfo &callInfo);
|
||||
InliningStatus inlineIsObject(CallInfo &callInfo);
|
||||
InliningStatus inlineHaveSameClass(CallInfo &callInfo);
|
||||
InliningStatus inlineToObject(CallInfo &callInfo);
|
||||
InliningStatus inlineToInteger(CallInfo &callInfo);
|
||||
|
|
|
@ -5789,6 +5789,16 @@ class LIsCallable : public LInstructionHelper<1, 1, 0>
|
|||
}
|
||||
};
|
||||
|
||||
class LIsObject : public LInstructionHelper<1, BOX_PIECES, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(IsObject);
|
||||
static const size_t Input = 0;
|
||||
MIsObject *mir() const {
|
||||
return mir_->toIsObject();
|
||||
}
|
||||
};
|
||||
|
||||
class LHaveSameClass : public LInstructionHelper<1, 2, 1>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -282,6 +282,7 @@
|
|||
_(SetDOMProperty) \
|
||||
_(CallDOMNative) \
|
||||
_(IsCallable) \
|
||||
_(IsObject) \
|
||||
_(HaveSameClass) \
|
||||
_(HasClass) \
|
||||
_(AsmJSLoadHeap) \
|
||||
|
|
|
@ -3429,6 +3429,17 @@ LIRGenerator::visitIsCallable(MIsCallable *ins)
|
|||
return define(new(alloc()) LIsCallable(useRegister(ins->object())), ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitIsObject(MIsObject *ins)
|
||||
{
|
||||
MDefinition *opd = ins->input();
|
||||
JS_ASSERT(opd->type() == MIRType_Value);
|
||||
LIsObject *lir = new(alloc()) LIsObject();
|
||||
if (!useBoxAtStart(lir, LIsObject::Input, opd))
|
||||
return false;
|
||||
return define(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitHaveSameClass(MHaveSameClass *ins)
|
||||
{
|
||||
|
|
|
@ -245,6 +245,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
bool visitCallInstanceOf(MCallInstanceOf *ins);
|
||||
bool visitProfilerStackOp(MProfilerStackOp *ins);
|
||||
bool visitIsCallable(MIsCallable *ins);
|
||||
bool visitIsObject(MIsObject *ins);
|
||||
bool visitHaveSameClass(MHaveSameClass *ins);
|
||||
bool visitHasClass(MHasClass *ins);
|
||||
bool visitAsmJSLoadGlobalVar(MAsmJSLoadGlobalVar *ins);
|
||||
|
|
|
@ -163,6 +163,8 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSFunction *target)
|
|||
return inlineHaveSameClass(callInfo);
|
||||
if (native == intrinsic_ToObject)
|
||||
return inlineToObject(callInfo);
|
||||
if (native == intrinsic_IsObject)
|
||||
return inlineIsObject(callInfo);
|
||||
if (native == intrinsic_ToInteger)
|
||||
return inlineToInteger(callInfo);
|
||||
if (native == intrinsic_ToString)
|
||||
|
@ -1902,6 +1904,21 @@ IonBuilder::inlineIsCallable(CallInfo &callInfo)
|
|||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineIsObject(CallInfo &callInfo)
|
||||
{
|
||||
if (callInfo.argc() != 1 || callInfo.constructing())
|
||||
return InliningStatus_NotInlined;
|
||||
if (getInlineReturnType() != MIRType_Boolean)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
MIsObject *isObject = MIsObject::New(alloc(), callInfo.getArg(0));
|
||||
current->add(isObject);
|
||||
current->push(isObject);
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineToObject(CallInfo &callInfo)
|
||||
{
|
||||
|
|
|
@ -10094,7 +10094,32 @@ class MIsCallable
|
|||
static MIsCallable *New(TempAllocator &alloc, MDefinition *obj) {
|
||||
return new(alloc) MIsCallable(obj);
|
||||
}
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
MDefinition *object() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
class MIsObject
|
||||
: public MUnaryInstruction,
|
||||
public BoxInputsPolicy
|
||||
{
|
||||
explicit MIsObject(MDefinition *object)
|
||||
: MUnaryInstruction(object)
|
||||
{
|
||||
setResultType(MIRType_Boolean);
|
||||
setMovable();
|
||||
}
|
||||
public:
|
||||
INSTRUCTION_HEADER(IsObject);
|
||||
static MIsObject *New(TempAllocator &alloc, MDefinition *obj) {
|
||||
return new(alloc) MIsObject(obj);
|
||||
}
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -197,6 +197,7 @@ namespace jit {
|
|||
_(GetDOMMember) \
|
||||
_(SetDOMProperty) \
|
||||
_(IsCallable) \
|
||||
_(IsObject) \
|
||||
_(HaveSameClass) \
|
||||
_(HasClass) \
|
||||
_(AsmJSNeg) \
|
||||
|
|
|
@ -306,6 +306,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
|||
SAFE_OP(FunctionDispatch)
|
||||
SAFE_OP(TypeObjectDispatch)
|
||||
SAFE_OP(IsCallable)
|
||||
SAFE_OP(IsObject)
|
||||
SAFE_OP(HaveSameClass)
|
||||
SAFE_OP(HasClass)
|
||||
UNSAFE_OP(EffectiveAddress)
|
||||
|
|
|
@ -1508,6 +1508,12 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
|||
cond = testNull(cond, value);
|
||||
emitSet(cond, dest);
|
||||
}
|
||||
|
||||
void testObjectSet(Condition cond, const ValueOperand &value, Register dest) {
|
||||
cond = testObject(cond, value);
|
||||
emitSet(cond, dest);
|
||||
}
|
||||
|
||||
void testUndefinedSet(Condition cond, const ValueOperand &value, Register dest) {
|
||||
cond = testUndefined(cond, value);
|
||||
emitSet(cond, dest);
|
||||
|
|
|
@ -2298,6 +2298,12 @@ MacroAssemblerMIPSCompat::branchTestObject(Condition cond, const BaseIndex &src,
|
|||
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_OBJECT), label, cond);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSCompat::testObjectSet(Condition cond, const ValueOperand &value, Register dest)
|
||||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ma_cmp_set(dest, value.typeReg(), ImmType(JSVAL_TYPE_OBJECT), cond);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSCompat::branchTestString(Condition cond, const ValueOperand &value, Label *label)
|
||||
|
|
|
@ -686,6 +686,7 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
|
|||
void branchTestObject(Condition cond, const ValueOperand &value, Label *label);
|
||||
void branchTestObject(Condition cond, Register tag, Label *label);
|
||||
void branchTestObject(Condition cond, const BaseIndex &src, Label *label);
|
||||
void testObjectSet(Condition cond, const ValueOperand &value, Register dest);
|
||||
|
||||
void branchTestString(Condition cond, const ValueOperand &value, Label *label);
|
||||
void branchTestString(Condition cond, Register tag, Label *label);
|
||||
|
|
|
@ -1029,6 +1029,12 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
|||
cond = testNull(cond, value);
|
||||
emitSet(cond, dest);
|
||||
}
|
||||
|
||||
void testObjectSet(Condition cond, const ValueOperand &value, Register dest) {
|
||||
cond = testObject(cond, value);
|
||||
emitSet(cond, dest);
|
||||
}
|
||||
|
||||
void testUndefinedSet(Condition cond, const ValueOperand &value, Register dest) {
|
||||
cond = testUndefined(cond, value);
|
||||
emitSet(cond, dest);
|
||||
|
|
|
@ -486,6 +486,12 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
|||
cond = testNull(cond, value);
|
||||
emitSet(cond, dest);
|
||||
}
|
||||
|
||||
void testObjectSet(Condition cond, const ValueOperand &value, Register dest) {
|
||||
cond = testObject(cond, value);
|
||||
emitSet(cond, dest);
|
||||
}
|
||||
|
||||
void testUndefinedSet(Condition cond, const ValueOperand &value, Register dest) {
|
||||
cond = testUndefined(cond, value);
|
||||
emitSet(cond, dest);
|
||||
|
|
|
@ -1007,6 +1007,7 @@ class ContextAllocPolicy
|
|||
|
||||
/* Exposed intrinsics so that Ion may inline them. */
|
||||
bool intrinsic_ToObject(JSContext *cx, unsigned argc, Value *vp);
|
||||
bool intrinsic_IsObject(JSContext *cx, unsigned argc, Value *vp);
|
||||
bool intrinsic_ToInteger(JSContext *cx, unsigned argc, Value *vp);
|
||||
bool intrinsic_ToString(JSContext *cx, unsigned argc, Value *vp);
|
||||
bool intrinsic_IsCallable(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
|
|
@ -63,6 +63,16 @@ js::intrinsic_ToObject(JSContext *cx, unsigned argc, Value *vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::intrinsic_IsObject(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
Value val = args[0];
|
||||
bool isObject = val.isObject();
|
||||
args.rval().setBoolean(isObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::intrinsic_ToInteger(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
|
@ -766,6 +776,7 @@ intrinsic_RuntimeDefaultLocale(JSContext *cx, unsigned argc, Value *vp)
|
|||
|
||||
static const JSFunctionSpec intrinsic_functions[] = {
|
||||
JS_FN("ToObject", intrinsic_ToObject, 1,0),
|
||||
JS_FN("IsObject", intrinsic_IsObject, 1,0),
|
||||
JS_FN("ToInteger", intrinsic_ToInteger, 1,0),
|
||||
JS_FN("ToString", intrinsic_ToString, 1,0),
|
||||
JS_FN("IsCallable", intrinsic_IsCallable, 1,0),
|
||||
|
|
Загрузка…
Ссылка в новой задаче