mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 844882 - Part 4: Ion inlining for self-hosted classes. (r=jandem)
This commit is contained in:
parent
6e6c2d3aed
commit
6072f225c5
@ -2741,6 +2741,10 @@ class OutOfLineNewObject : public OutOfLineCodeBase<CodeGenerator>
|
||||
typedef JSObject *(*NewInitObjectFn)(JSContext *, HandleObject);
|
||||
static const VMFunction NewInitObjectInfo = FunctionInfo<NewInitObjectFn>(NewInitObject);
|
||||
|
||||
typedef JSObject *(*NewInitObjectWithClassPrototypeFn)(JSContext *, HandleObject);
|
||||
static const VMFunction NewInitObjectWithClassPrototypeInfo =
|
||||
FunctionInfo<NewInitObjectWithClassPrototypeFn>(NewInitObjectWithClassPrototype);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitNewObjectVMCall(LNewObject *lir)
|
||||
{
|
||||
@ -2752,8 +2756,17 @@ CodeGenerator::visitNewObjectVMCall(LNewObject *lir)
|
||||
saveLive(lir);
|
||||
|
||||
pushArg(ImmGCPtr(lir->mir()->templateObject()));
|
||||
if (!callVM(NewInitObjectInfo, lir))
|
||||
|
||||
// If we're making a new object with a class prototype (that is, an object
|
||||
// that derives its class from its prototype instead of being
|
||||
// ObjectClass'd) from self-hosted code, we need a different init
|
||||
// function.
|
||||
if (lir->mir()->templateObjectIsClassPrototype()) {
|
||||
if (!callVM(NewInitObjectWithClassPrototypeInfo, lir))
|
||||
return false;
|
||||
} else if (!callVM(NewInitObjectInfo, lir)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReturnReg != objReg)
|
||||
masm.movePtr(ReturnReg, objReg);
|
||||
@ -6828,6 +6841,22 @@ CodeGenerator::visitOutOfLinePropagateParallelAbort(OutOfLinePropagateParallelAb
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitHaveSameClass(LHaveSameClass *ins)
|
||||
{
|
||||
Register lhs = ToRegister(ins->lhs());
|
||||
Register rhs = ToRegister(ins->rhs());
|
||||
Register temp = ToRegister(ins->getTemp(0));
|
||||
Register output = ToRegister(ins->output());
|
||||
|
||||
masm.loadObjClass(lhs, temp);
|
||||
masm.loadObjClass(rhs, output);
|
||||
masm.cmpPtr(temp, output);
|
||||
masm.emitSet(Assembler::Equal, output);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitAsmJSCall(LAsmJSCall *ins)
|
||||
{
|
||||
|
@ -238,6 +238,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitCallDOMNative(LCallDOMNative *lir);
|
||||
bool visitCallGetIntrinsicValue(LCallGetIntrinsicValue *lir);
|
||||
bool visitIsCallable(LIsCallable *lir);
|
||||
bool visitHaveSameClass(LHaveSameClass *lir);
|
||||
bool visitAsmJSCall(LAsmJSCall *lir);
|
||||
bool visitAsmJSParameter(LAsmJSParameter *lir);
|
||||
bool visitAsmJSReturn(LAsmJSReturn *ret);
|
||||
|
@ -5228,7 +5228,8 @@ IonBuilder::jsop_newobject(HandleObject baseObj)
|
||||
templateObject->setType(type);
|
||||
}
|
||||
|
||||
MNewObject *ins = MNewObject::New(templateObject);
|
||||
MNewObject *ins = MNewObject::New(templateObject,
|
||||
/* templateObjectIsClassPrototype = */ false);
|
||||
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
@ -509,6 +509,8 @@ class IonBuilder : public MIRGenerator
|
||||
// Utility intrinsics.
|
||||
InliningStatus inlineThrowError(CallInfo &callInfo);
|
||||
InliningStatus inlineIsCallable(CallInfo &callInfo);
|
||||
InliningStatus inlineNewObjectWithClassPrototype(CallInfo &callInfo);
|
||||
InliningStatus inlineHaveSameClass(CallInfo &callInfo);
|
||||
InliningStatus inlineToObject(CallInfo &callInfo);
|
||||
InliningStatus inlineDump(CallInfo &callInfo);
|
||||
|
||||
|
@ -4567,6 +4567,28 @@ class LIsCallable : public LInstructionHelper<1, 1, 0>
|
||||
}
|
||||
};
|
||||
|
||||
class LHaveSameClass : public LInstructionHelper<1, 2, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(HaveSameClass);
|
||||
LHaveSameClass(const LAllocation &left, const LAllocation &right,
|
||||
const LDefinition &temp) {
|
||||
setOperand(0, left);
|
||||
setOperand(1, right);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LAllocation *lhs() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LAllocation *rhs() {
|
||||
return getOperand(1);
|
||||
}
|
||||
MHaveSameClass *mir() const {
|
||||
return mir_->toHaveSameClass();
|
||||
}
|
||||
};
|
||||
|
||||
class LAsmJSLoadHeap : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
|
@ -226,6 +226,7 @@
|
||||
_(SetDOMProperty) \
|
||||
_(CallDOMNative) \
|
||||
_(IsCallable) \
|
||||
_(HaveSameClass) \
|
||||
_(AsmJSLoadHeap) \
|
||||
_(AsmJSStoreHeap) \
|
||||
_(AsmJSLoadGlobalVar) \
|
||||
|
@ -2636,6 +2636,18 @@ LIRGenerator::visitIsCallable(MIsCallable *ins)
|
||||
return define(new LIsCallable(useRegister(ins->object())), ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitHaveSameClass(MHaveSameClass *ins)
|
||||
{
|
||||
MDefinition *lhs = ins->lhs();
|
||||
MDefinition *rhs = ins->rhs();
|
||||
|
||||
JS_ASSERT(lhs->type() == MIRType_Object);
|
||||
JS_ASSERT(rhs->type() == MIRType_Object);
|
||||
|
||||
return define(new LHaveSameClass(useRegister(lhs), useRegister(rhs), temp()), ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitAsmJSLoadHeap(MAsmJSLoadHeap *ins)
|
||||
{
|
||||
|
@ -231,6 +231,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
bool visitCallInstanceOf(MCallInstanceOf *ins);
|
||||
bool visitFunctionBoundary(MFunctionBoundary *ins);
|
||||
bool visitIsCallable(MIsCallable *ins);
|
||||
bool visitHaveSameClass(MHaveSameClass *ins);
|
||||
bool visitAsmJSLoadHeap(MAsmJSLoadHeap *ins);
|
||||
bool visitAsmJSLoadGlobalVar(MAsmJSLoadGlobalVar *ins);
|
||||
bool visitAsmJSStoreGlobalVar(MAsmJSStoreGlobalVar *ins);
|
||||
|
@ -114,6 +114,10 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
|
||||
return inlineThrowError(callInfo);
|
||||
if (native == intrinsic_IsCallable)
|
||||
return inlineIsCallable(callInfo);
|
||||
if (native == intrinsic_NewObjectWithClassPrototype)
|
||||
return inlineNewObjectWithClassPrototype(callInfo);
|
||||
if (native == intrinsic_HaveSameClass)
|
||||
return inlineHaveSameClass(callInfo);
|
||||
if (native == intrinsic_ToObject)
|
||||
return inlineToObject(callInfo);
|
||||
#ifdef DEBUG
|
||||
@ -1351,6 +1355,64 @@ IonBuilder::inlineUnsafeGetReservedSlot(CallInfo &callInfo)
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineNewObjectWithClassPrototype(CallInfo &callInfo)
|
||||
{
|
||||
if (callInfo.argc() != 1 || callInfo.constructing())
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.getArg(0)->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition *arg = callInfo.getArg(0)->toPassArg()->getArgument();
|
||||
if (!arg->isConstant())
|
||||
return InliningStatus_NotInlined;
|
||||
JSObject *proto = &arg->toConstant()->value().toObject();
|
||||
|
||||
JSObject *templateObject = NewObjectWithGivenProto(cx, proto->getClass(), proto, cx->global());
|
||||
if (!templateObject)
|
||||
return InliningStatus_Error;
|
||||
|
||||
MNewObject *newObj = MNewObject::New(templateObject,
|
||||
/* templateObjectIsClassPrototype = */ true);
|
||||
current->add(newObj);
|
||||
current->push(newObj);
|
||||
|
||||
if (!resumeAfter(newObj))
|
||||
return InliningStatus_Error;
|
||||
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineHaveSameClass(CallInfo &callInfo)
|
||||
{
|
||||
if (callInfo.argc() != 2 || callInfo.constructing())
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.getArg(0)->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.getArg(1)->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::StackTypeSet *arg1Types = callInfo.getArg(0)->resultTypeSet();
|
||||
types::StackTypeSet *arg2Types = callInfo.getArg(1)->resultTypeSet();
|
||||
Class *arg1Clasp = arg1Types ? arg1Types->getKnownClass() : NULL;
|
||||
Class *arg2Clasp = arg2Types ? arg1Types->getKnownClass() : NULL;
|
||||
if (arg1Clasp && arg2Clasp) {
|
||||
MConstant *constant = MConstant::New(BooleanValue(arg1Clasp == arg2Clasp));
|
||||
current->add(constant);
|
||||
current->push(constant);
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
callInfo.unwrapArgs();
|
||||
|
||||
MHaveSameClass *sameClass = MHaveSameClass::New(callInfo.getArg(0), callInfo.getArg(1));
|
||||
current->add(sameClass);
|
||||
current->push(sameClass);
|
||||
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineThrowError(CallInfo &callInfo)
|
||||
{
|
||||
|
@ -1184,10 +1184,13 @@ class MNewArray : public MNullaryInstruction
|
||||
class MNewObject : public MNullaryInstruction
|
||||
{
|
||||
CompilerRootObject templateObject_;
|
||||
bool templateObjectIsClassPrototype_;
|
||||
|
||||
MNewObject(JSObject *templateObject)
|
||||
: templateObject_(templateObject)
|
||||
MNewObject(JSObject *templateObject, bool templateObjectIsClassPrototype)
|
||||
: templateObject_(templateObject),
|
||||
templateObjectIsClassPrototype_(templateObjectIsClassPrototype)
|
||||
{
|
||||
JS_ASSERT_IF(templateObjectIsClassPrototype, !shouldUseVM());
|
||||
setResultType(MIRType_Object);
|
||||
setResultTypeSet(MakeSingletonTypeSet(templateObject));
|
||||
}
|
||||
@ -1195,14 +1198,18 @@ class MNewObject : public MNullaryInstruction
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewObject)
|
||||
|
||||
static MNewObject *New(JSObject *templateObject) {
|
||||
return new MNewObject(templateObject);
|
||||
static MNewObject *New(JSObject *templateObject, bool templateObjectIsClassPrototype) {
|
||||
return new MNewObject(templateObject, templateObjectIsClassPrototype);
|
||||
}
|
||||
|
||||
// Returns true if the code generator should call through to the
|
||||
// VM rather than the fast path.
|
||||
bool shouldUseVM() const;
|
||||
|
||||
bool templateObjectIsClassPrototype() const {
|
||||
return templateObjectIsClassPrototype_;
|
||||
}
|
||||
|
||||
JSObject *templateObject() const {
|
||||
return templateObject_;
|
||||
}
|
||||
@ -7847,6 +7854,35 @@ class MIsCallable
|
||||
MDefinition *object() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
class MHaveSameClass
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1> >
|
||||
{
|
||||
MHaveSameClass(MDefinition *left, MDefinition *right)
|
||||
: MBinaryInstruction(left, right)
|
||||
{
|
||||
setResultType(MIRType_Boolean);
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(HaveSameClass);
|
||||
|
||||
static MHaveSameClass *New(MDefinition *left, MDefinition *right) {
|
||||
return new MHaveSameClass(left, right);
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
class MAsmJSNeg : public MUnaryInstruction
|
||||
|
@ -168,6 +168,7 @@ namespace ion {
|
||||
_(GetDOMProperty) \
|
||||
_(SetDOMProperty) \
|
||||
_(IsCallable) \
|
||||
_(HaveSameClass) \
|
||||
_(AsmJSNeg) \
|
||||
_(AsmJSUDiv) \
|
||||
_(AsmJSUMod) \
|
||||
|
@ -276,6 +276,7 @@ class ParallelArrayVisitor : public MInstructionVisitor
|
||||
SAFE_OP(FunctionDispatch)
|
||||
SAFE_OP(TypeObjectDispatch)
|
||||
SAFE_OP(IsCallable)
|
||||
SAFE_OP(HaveSameClass)
|
||||
UNSAFE_OP(EffectiveAddress)
|
||||
UNSAFE_OP(AsmJSUnsignedToDouble)
|
||||
UNSAFE_OP(AsmJSNeg)
|
||||
|
@ -289,6 +289,23 @@ NewInitObject(JSContext *cx, HandleObject templateObject)
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
NewInitObjectWithClassPrototype(JSContext *cx, HandleObject templateObject)
|
||||
{
|
||||
JS_ASSERT(!templateObject->hasSingletonType());
|
||||
|
||||
JSObject *obj = NewObjectWithGivenProto(cx,
|
||||
templateObject->getClass(),
|
||||
templateObject->getProto(),
|
||||
cx->global());
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
obj->setType(templateObject->type());
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
|
||||
{
|
||||
|
@ -557,6 +557,7 @@ bool IteratorMore(JSContext *cx, HandleObject obj, JSBool *res);
|
||||
JSObject *NewInitParallelArray(JSContext *cx, HandleObject templateObj);
|
||||
JSObject *NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *type);
|
||||
JSObject *NewInitObject(JSContext *cx, HandleObject templateObject);
|
||||
JSObject *NewInitObjectWithClassPrototype(JSContext *cx, HandleObject templateObject);
|
||||
|
||||
bool ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval);
|
||||
bool ArrayPushDense(JSContext *cx, HandleObject obj, HandleValue v, uint32_t *length);
|
||||
|
@ -2363,6 +2363,7 @@ JSBool intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp);
|
||||
JSBool intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp);
|
||||
JSBool intrinsic_UnsafeSetReservedSlot(JSContext *cx, unsigned argc, Value *vp);
|
||||
JSBool intrinsic_UnsafeGetReservedSlot(JSContext *cx, unsigned argc, Value *vp);
|
||||
JSBool intrinsic_NewObjectWithClassPrototype(JSContext *cx, unsigned argc, Value *vp);
|
||||
JSBool intrinsic_HaveSameClass(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
JSBool intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
@ -505,8 +505,8 @@ intrinsic_NewClassPrototype(JSContext *cx, unsigned argc, Value *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
intrinsic_NewObjectWithClassPrototype(JSContext *cx, unsigned argc, Value *vp)
|
||||
JSBool
|
||||
js::intrinsic_NewObjectWithClassPrototype(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
JS_ASSERT(args.length() == 1);
|
||||
|
Loading…
Reference in New Issue
Block a user