Bug 844887 - Inline IsCallable and ToObject intrinsics in Ion. (r=sstangl)

This commit is contained in:
Shu-yu Guo 2013-04-18 17:41:43 -07:00
Родитель bad51eb853
Коммит fbb393d573
13 изменённых файлов: 134 добавлений и 21 удалений

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

@ -6102,6 +6102,28 @@ CodeGenerator::visitOutOfLineParallelAbort(OutOfLineParallelAbort *ool)
return true;
}
bool
CodeGenerator::visitIsCallable(LIsCallable *ins)
{
Register object = ToRegister(ins->object());
Register output = ToRegister(ins->output());
masm.loadObjClass(object, output);
// An object is callable iff (isFunction() || getClass()->call).
Label notFunction, done;
masm.branchPtr(Assembler::NotEqual, output, ImmWord(&js::FunctionClass), &notFunction);
masm.move32(Imm32(1), output);
masm.jump(&done);
masm.bind(&notFunction);
masm.cmpPtr(Address(output, offsetof(js::Class, call)), ImmWord((void *)NULL));
masm.emitSet(Assembler::NonZero, output);
masm.bind(&done);
return true;
}
bool
CodeGenerator::visitAsmJSCall(LAsmJSCall *ins)
{

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

@ -217,6 +217,7 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitSetDOMProperty(LSetDOMProperty *lir);
bool visitCallDOMNative(LCallDOMNative *lir);
bool visitCallGetIntrinsicValue(LCallGetIntrinsicValue *lir);
bool visitIsCallable(LIsCallable *lir);
bool visitAsmJSCall(LAsmJSCall *lir);
bool visitAsmJSParameter(LAsmJSParameter *lir);
bool visitAsmJSReturn(LAsmJSReturn *ret);

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

@ -460,6 +460,8 @@ class IonBuilder : public MIRGenerator
uint32_t discards);
InliningStatus inlineThrowError(CallInfo &callInfo);
InliningStatus inlineIsCallable(CallInfo &callInfo);
InliningStatus inlineToObject(CallInfo &callInfo);
InliningStatus inlineDump(CallInfo &callInfo);
// Main inlining functions

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

@ -4162,6 +4162,22 @@ class LFunctionBoundary : public LInstructionHelper<0, 0, 1>
}
};
class LIsCallable : public LInstructionHelper<1, 1, 0>
{
public:
LIR_HEADER(IsCallable);
LIsCallable(const LAllocation &object) {
setOperand(0, object);
}
const LAllocation *object() {
return getOperand(0);
}
MIsCallable *mir() const {
return mir_->toIsCallable();
}
};
class LAsmJSLoadHeap : public LInstructionHelper<1, 1, 0>
{
public:

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

@ -210,6 +210,7 @@
_(GetDOMProperty) \
_(SetDOMProperty) \
_(CallDOMNative) \
_(IsCallable) \
_(AsmJSLoadHeap) \
_(AsmJSStoreHeap) \
_(AsmJSLoadGlobalVar) \

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

@ -2461,6 +2461,14 @@ LIRGenerator::visitFunctionBoundary(MFunctionBoundary *ins)
assignSafepoint(lir, ins);
}
bool
LIRGenerator::visitIsCallable(MIsCallable *ins)
{
JS_ASSERT(ins->object()->type() == MIRType_Object);
JS_ASSERT(ins->type() == MIRType_Boolean);
return define(new LIsCallable(useRegister(ins->object())), ins);
}
bool
LIRGenerator::visitAsmJSLoadHeap(MAsmJSLoadHeap *ins)
{

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

@ -220,6 +220,7 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitInstanceOf(MInstanceOf *ins);
bool visitCallInstanceOf(MCallInstanceOf *ins);
bool visitFunctionBoundary(MFunctionBoundary *ins);
bool visitIsCallable(MIsCallable *ins);
bool visitAsmJSLoadHeap(MAsmJSLoadHeap *ins);
bool visitAsmJSLoadGlobalVar(MAsmJSLoadGlobalVar *ins);
bool visitAsmJSStoreGlobalVar(MAsmJSStoreGlobalVar *ins);

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

@ -85,25 +85,25 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
if (native == regexp_test)
return inlineRegExpTest(callInfo);
// Parallel Array
// Array intrinsics.
if (native == intrinsic_UnsafeSetElement)
return inlineUnsafeSetElement(callInfo);
if (native == testingFunc_inParallelSection)
return inlineShouldForceSequentialOrInParallelSection(callInfo);
if (native == intrinsic_NewDenseArray)
return inlineNewDenseArray(callInfo);
// Self-hosting
// Utility intrinsics.
if (native == intrinsic_ThrowError)
return inlineThrowError(callInfo);
if (native == intrinsic_IsCallable)
return inlineIsCallable(callInfo);
if (native == intrinsic_ToObject)
return inlineToObject(callInfo);
#ifdef DEBUG
if (native == intrinsic_Dump)
return inlineDump(callInfo);
#endif
// Parallel Array
if (native == intrinsic_UnsafeSetElement)
return inlineUnsafeSetElement(callInfo);
// Parallel intrinsics.
if (native == intrinsic_ShouldForceSequential)
return inlineShouldForceSequentialOrInParallelSection(callInfo);
if (native == testingFunc_inParallelSection)
@ -112,16 +112,6 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
return inlineNewParallelArray(callInfo);
if (native == ParallelArrayObject::construct)
return inlineParallelArray(callInfo);
if (native == intrinsic_NewDenseArray)
return inlineNewDenseArray(callInfo);
// Self-hosting
if (native == intrinsic_ThrowError)
return inlineThrowError(callInfo);
#ifdef DEBUG
if (native == intrinsic_Dump)
return inlineDump(callInfo);
#endif
return InliningStatus_NotInlined;
}
@ -1317,6 +1307,51 @@ IonBuilder::inlineThrowError(CallInfo &callInfo)
return InliningStatus_Inlined;
}
IonBuilder::InliningStatus
IonBuilder::inlineIsCallable(CallInfo &callInfo)
{
if (callInfo.argc() != 1 || callInfo.constructing())
return InliningStatus_NotInlined;
if (getInlineReturnType() != MIRType_Boolean)
return InliningStatus_NotInlined;
if (getInlineArgType(callInfo, 0) != MIRType_Object)
return InliningStatus_NotInlined;
callInfo.unwrapArgs();
MIsCallable *isCallable = MIsCallable::New(callInfo.getArg(0));
current->add(isCallable);
current->push(isCallable);
return InliningStatus_Inlined;
}
IonBuilder::InliningStatus
IonBuilder::inlineToObject(CallInfo &callInfo)
{
if (callInfo.argc() != 1 || callInfo.constructing())
return InliningStatus_NotInlined;
// If we know the input type is an object, nop ToObject.
if (getInlineReturnType() != MIRType_Object)
return InliningStatus_NotInlined;
if (getInlineArgType(callInfo, 0) != MIRType_Object)
return InliningStatus_NotInlined;
callInfo.unwrapArgs();
MDefinition *object = callInfo.getArg(0);
// TI still expects the barrier to be checked, since this was a native
// call. We manually make a MTypeBarrier here to avoid pointless
// boxing-unbox sequences.
MTypeBarrier *barrier = MTypeBarrier::New(object, cloneTypeSet(callInfo.barrier()));
current->add(barrier);
current->push(object);
return InliningStatus_Inlined;
}
IonBuilder::InliningStatus
IonBuilder::inlineDump(CallInfo &callInfo)
{

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

@ -7172,6 +7172,29 @@ class FlattenedMResumePointIter
}
};
class MIsCallable
: public MUnaryInstruction,
public SingleObjectPolicy
{
MIsCallable(MDefinition *object)
: MUnaryInstruction(object)
{
setResultType(MIRType_Boolean);
setMovable();
}
public:
INSTRUCTION_HEADER(IsCallable);
static MIsCallable *New(MDefinition *obj) {
return new MIsCallable(obj);
}
MDefinition *object() const {
return getOperand(0);
}
};
class MAsmJSNeg : public MUnaryInstruction
{
MAsmJSNeg(MDefinition *op, MIRType type)

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

@ -156,6 +156,7 @@ namespace ion {
_(FunctionBoundary) \
_(GetDOMProperty) \
_(SetDOMProperty) \
_(IsCallable) \
_(AsmJSNeg) \
_(AsmJSUDiv) \
_(AsmJSUMod) \

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

@ -264,6 +264,7 @@ class ParallelArrayVisitor : public MInstructionVisitor
SAFE_OP(PolyInlineDispatch)
SAFE_OP(FunctionDispatch)
SAFE_OP(TypeObjectDispatch)
SAFE_OP(IsCallable)
UNSAFE_OP(EffectiveAddress)
UNSAFE_OP(AsmJSUnsignedToDouble)
UNSAFE_OP(AsmJSNeg)

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

@ -2393,6 +2393,8 @@ class ContextAllocPolicy
void reportAllocOverflow() const { js_ReportAllocationOverflow(cx_); }
};
JSBool intrinsic_ToObject(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_IsCallable(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp);

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

@ -43,8 +43,8 @@ static JSClass self_hosting_global_class = {
JS_ConvertStub, NULL
};
static JSBool
intrinsic_ToObject(JSContext *cx, unsigned argc, Value *vp)
JSBool
js::intrinsic_ToObject(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedValue val(cx, args[0]);
@ -66,8 +66,8 @@ intrinsic_ToInteger(JSContext *cx, unsigned argc, Value *vp)
return true;
}
static JSBool
intrinsic_IsCallable(JSContext *cx, unsigned argc, Value *vp)
JSBool
js::intrinsic_IsCallable(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
Value val = args[0];