Bug 1021739 - Transform the selfhosting IsObject function into an intrinsic, r=h4writer

This commit is contained in:
Conner McConkey 2014-06-30 12:32:05 +02:00
Родитель 2711b03876
Коммит 821c5897ee
19 изменённых файлов: 115 добавлений и 16 удалений

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

@ -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),