mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 987807 - Split a NewSingletonCallObject out of NewCallObject. This produces slightly leaner code and creates all call objects with the correct type initial type from birth. r=terrence
--HG-- extra : rebase_source : 6b27082de6e5c05e0bf672d56a8701a39c8c7090
This commit is contained in:
parent
640a8498c2
commit
e2d24041ab
@ -3537,8 +3537,7 @@ CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject *(*NewCallObjectFn)(JSContext *, HandleScript, HandleShape,
|
||||
HandleTypeObject, HeapSlot *);
|
||||
typedef JSObject *(*NewCallObjectFn)(JSContext *, HandleShape, HandleTypeObject, HeapSlot *);
|
||||
static const VMFunction NewCallObjectInfo =
|
||||
FunctionInfo<NewCallObjectFn>(NewCallObject);
|
||||
|
||||
@ -3550,48 +3549,78 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir)
|
||||
|
||||
JSObject *templateObj = lir->mir()->templateObject();
|
||||
|
||||
// If we have a template object, we can inline call object creation.
|
||||
OutOfLineCode *ool;
|
||||
if (lir->slots()->isRegister()) {
|
||||
ool = oolCallVM(NewCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(lir->mir()->block()->info().script()),
|
||||
ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmGCPtr(templateObj->hasSingletonType() ? nullptr : templateObj->type()),
|
||||
(ArgList(), ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmGCPtr(templateObj->type()),
|
||||
ToRegister(lir->slots())),
|
||||
StoreRegisterTo(objReg));
|
||||
} else {
|
||||
ool = oolCallVM(NewCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(lir->mir()->block()->info().script()),
|
||||
ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmGCPtr(templateObj->hasSingletonType() ? nullptr : templateObj->type()),
|
||||
(ArgList(), ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmGCPtr(templateObj->type()),
|
||||
ImmPtr(nullptr)),
|
||||
StoreRegisterTo(objReg));
|
||||
}
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
if (lir->mir()->needsSingletonType()
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
// Slot initialization is not barriered in this case, so we must either
|
||||
if (ins->templateObject()->hasDynamicSlots()) {
|
||||
// Slot initialization is unbarriered in this case, so we must either
|
||||
// allocate in the nursery or bail if that is not possible.
|
||||
|| lir->mir()->templateObject()->hasDynamicSlots()
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Objects can only be given singleton types in VM calls.
|
||||
masm.jump(ool->entry());
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Inline call object creation, using the OOL path only for tricky cases.
|
||||
masm.newGCThing(objReg, tempReg, templateObj, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(objReg, tempReg, templateObj);
|
||||
|
||||
if (lir->slots()->isRegister())
|
||||
masm.storePtr(ToRegister(lir->slots()), Address(objReg, JSObject::offsetOfSlots()));
|
||||
}
|
||||
|
||||
if (lir->slots()->isRegister())
|
||||
masm.storePtr(ToRegister(lir->slots()), Address(objReg, JSObject::offsetOfSlots()));
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject *(*NewSingletonCallObjectFn)(JSContext *, HandleShape, HeapSlot *);
|
||||
static const VMFunction NewSingletonCallObjectInfo =
|
||||
FunctionInfo<NewSingletonCallObjectFn>(NewSingletonCallObject);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitNewSingletonCallObject(LNewSingletonCallObject *lir)
|
||||
{
|
||||
Register objReg = ToRegister(lir->output());
|
||||
|
||||
JSObject *templateObj = lir->mir()->templateObject();
|
||||
|
||||
OutOfLineCode *ool;
|
||||
if (lir->slots()->isRegister()) {
|
||||
ool = oolCallVM(NewSingletonCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(templateObj->lastProperty()),
|
||||
ToRegister(lir->slots())),
|
||||
StoreRegisterTo(objReg));
|
||||
} else {
|
||||
ool = oolCallVM(NewSingletonCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmPtr(nullptr)),
|
||||
StoreRegisterTo(objReg));
|
||||
}
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
// Objects can only be given singleton types in VM calls. We make the call
|
||||
// out of line to not bloat inline code, even if (naively) this seems like
|
||||
// extra work.
|
||||
masm.jump(ool->entry());
|
||||
masm.bind(ool->rejoin());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitNewCallObjectPar(LNewCallObjectPar *lir)
|
||||
{
|
||||
|
@ -140,6 +140,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitOutOfLineNewObject(OutOfLineNewObject *ool);
|
||||
bool visitNewDeclEnvObject(LNewDeclEnvObject *lir);
|
||||
bool visitNewCallObject(LNewCallObject *lir);
|
||||
bool visitNewSingletonCallObject(LNewSingletonCallObject *lir);
|
||||
bool visitNewCallObjectPar(LNewCallObjectPar *lir);
|
||||
bool visitNewStringObject(LNewStringObject *lir);
|
||||
bool visitNewPar(LNewPar *lir);
|
||||
|
@ -4682,7 +4682,11 @@ IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
|
||||
// instructions could potentially bailout, thus leaking the dynamic slots
|
||||
// pointer. Run-once scripts need a singleton type, so always do a VM call
|
||||
// in such cases.
|
||||
MNewCallObject *callObj = MNewCallObject::New(alloc(), templateObj, script()->treatAsRunOnce(), slots);
|
||||
MUnaryInstruction *callObj;
|
||||
if (script()->treatAsRunOnce())
|
||||
callObj = MNewRunOnceCallObject::New(alloc(), templateObj, slots);
|
||||
else
|
||||
callObj = MNewCallObject::New(alloc(), templateObj, slots);
|
||||
current->add(callObj);
|
||||
|
||||
// Initialize the object's reserved slots. No post barrier is needed here,
|
||||
|
@ -490,11 +490,36 @@ class LNewCallObject : public LInstructionHelper<1, 1, 1>
|
||||
const LAllocation *slots() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MNewCallObject *mir() const {
|
||||
return mir_->toNewCallObject();
|
||||
}
|
||||
};
|
||||
|
||||
// Allocates a new CallObject with singleton type through an out-of-line VM
|
||||
// call. The inputs are:
|
||||
// slots: either a reg representing a HeapSlot *, or a placeholder
|
||||
// meaning that no slots pointer is needed.
|
||||
//
|
||||
class LNewSingletonCallObject : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewSingletonCallObject)
|
||||
|
||||
LNewSingletonCallObject(const LAllocation &slots) {
|
||||
setOperand(0, slots);
|
||||
}
|
||||
|
||||
const LAllocation *slots() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MNewCallObjectBase * mir() const {
|
||||
MOZ_ASSERT(mir_->isNewCallObject() || mir_->isNewRunOnceCallObject());
|
||||
return static_cast<MNewCallObjectBase *>(mir_);
|
||||
}
|
||||
};
|
||||
|
||||
class LNewCallObjectPar : public LInstructionHelper<1, 2, 2>
|
||||
{
|
||||
LNewCallObjectPar(const LAllocation &cx, const LAllocation &slots,
|
||||
@ -2410,7 +2435,7 @@ class LMinMaxD : public LInstructionHelper<1, 2, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(MinMaxD)
|
||||
LMinMaxD(const LAllocation &first, const LAllocation &second)
|
||||
LMinMaxD(const LAllocation &first, const LAllocation &second)
|
||||
{
|
||||
setOperand(0, first);
|
||||
setOperand(1, second);
|
||||
|
@ -28,6 +28,7 @@
|
||||
_(NewSlots) \
|
||||
_(NewDeclEnvObject) \
|
||||
_(NewCallObject) \
|
||||
_(NewSingletonCallObject) \
|
||||
_(NewStringObject) \
|
||||
_(NewPar) \
|
||||
_(NewDenseArrayPar) \
|
||||
|
@ -201,7 +201,35 @@ LIRGenerator::visitNewCallObject(MNewCallObject *ins)
|
||||
else
|
||||
slots = LConstantIndex::Bogus();
|
||||
|
||||
LNewCallObject *lir = new(alloc()) LNewCallObject(slots, temp());
|
||||
LInstruction *lir;
|
||||
if (ins->templateObject()->hasSingletonType()) {
|
||||
LNewSingletonCallObject *singletonLir = new(alloc()) LNewSingletonCallObject(slots);
|
||||
if (!define(singletonLir, ins))
|
||||
return false;
|
||||
lir = singletonLir;
|
||||
} else {
|
||||
LNewCallObject *normalLir = new(alloc()) LNewCallObject(slots, temp());
|
||||
if (!define(normalLir, ins))
|
||||
return false;
|
||||
lir = normalLir;
|
||||
}
|
||||
|
||||
if (!assignSafepoint(lir, ins))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitNewRunOnceCallObject(MNewRunOnceCallObject *ins)
|
||||
{
|
||||
LAllocation slots;
|
||||
if (ins->slots()->type() == MIRType_Slots)
|
||||
slots = useRegister(ins->slots());
|
||||
else
|
||||
slots = LConstantIndex::Bogus();
|
||||
|
||||
LNewSingletonCallObject *lir = new(alloc()) LNewSingletonCallObject(slots);
|
||||
if (!define(lir, ins))
|
||||
return false;
|
||||
|
||||
|
@ -71,6 +71,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
bool visitNewObject(MNewObject *ins);
|
||||
bool visitNewDeclEnvObject(MNewDeclEnvObject *ins);
|
||||
bool visitNewCallObject(MNewCallObject *ins);
|
||||
bool visitNewRunOnceCallObject(MNewRunOnceCallObject *ins);
|
||||
bool visitNewStringObject(MNewStringObject *ins);
|
||||
bool visitNewDerivedTypedObject(MNewDerivedTypedObject *ins);
|
||||
bool visitNewPar(MNewPar *ins);
|
||||
|
@ -9018,42 +9018,62 @@ class MNewDeclEnvObject : public MNullaryInstruction
|
||||
}
|
||||
};
|
||||
|
||||
class MNewCallObject : public MUnaryInstruction
|
||||
class MNewCallObjectBase : public MUnaryInstruction
|
||||
{
|
||||
CompilerRootObject templateObj_;
|
||||
bool needsSingletonType_;
|
||||
|
||||
MNewCallObject(JSObject *templateObj, bool needsSingletonType, MDefinition *slots)
|
||||
protected:
|
||||
MNewCallObjectBase(JSObject *templateObj, MDefinition *slots)
|
||||
: MUnaryInstruction(slots),
|
||||
templateObj_(templateObj),
|
||||
needsSingletonType_(needsSingletonType)
|
||||
templateObj_(templateObj)
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewCallObject)
|
||||
|
||||
static MNewCallObject *New(TempAllocator &alloc, JSObject *templateObj, bool needsSingletonType,
|
||||
MDefinition *slots)
|
||||
{
|
||||
return new(alloc) MNewCallObject(templateObj, needsSingletonType, slots);
|
||||
}
|
||||
|
||||
MDefinition *slots() {
|
||||
return getOperand(0);
|
||||
}
|
||||
JSObject *templateObject() {
|
||||
return templateObj_;
|
||||
}
|
||||
bool needsSingletonType() const {
|
||||
return needsSingletonType_;
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
class MNewCallObject : public MNewCallObjectBase
|
||||
{
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewCallObject)
|
||||
|
||||
MNewCallObject(JSObject *templateObj, MDefinition *slots)
|
||||
: MNewCallObjectBase(templateObj, slots)
|
||||
{}
|
||||
|
||||
static MNewCallObject *
|
||||
New(TempAllocator &alloc, JSObject *templateObj, MDefinition *slots)
|
||||
{
|
||||
return new(alloc) MNewCallObject(templateObj, slots);
|
||||
}
|
||||
};
|
||||
|
||||
class MNewRunOnceCallObject : public MNewCallObjectBase
|
||||
{
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewRunOnceCallObject)
|
||||
|
||||
MNewRunOnceCallObject(JSObject *templateObj, MDefinition *slots)
|
||||
: MNewCallObjectBase(templateObj, slots)
|
||||
{}
|
||||
|
||||
static MNewRunOnceCallObject *
|
||||
New(TempAllocator &alloc, JSObject *templateObj, MDefinition *slots)
|
||||
{
|
||||
return new(alloc) MNewRunOnceCallObject(templateObj, slots);
|
||||
}
|
||||
};
|
||||
|
||||
class MNewCallObjectPar : public MBinaryInstruction
|
||||
{
|
||||
CompilerRootObject templateObj_;
|
||||
@ -9068,7 +9088,7 @@ class MNewCallObjectPar : public MBinaryInstruction
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewCallObjectPar);
|
||||
|
||||
static MNewCallObjectPar *New(TempAllocator &alloc, MDefinition *cx, MNewCallObject *callObj) {
|
||||
static MNewCallObjectPar *New(TempAllocator &alloc, MDefinition *cx, MNewCallObjectBase *callObj) {
|
||||
return new(alloc) MNewCallObjectPar(cx, callObj->templateObject(), callObj->slots());
|
||||
}
|
||||
|
||||
|
@ -90,6 +90,7 @@ namespace jit {
|
||||
_(NewObject) \
|
||||
_(NewDeclEnvObject) \
|
||||
_(NewCallObject) \
|
||||
_(NewRunOnceCallObject) \
|
||||
_(NewStringObject) \
|
||||
_(InitElem) \
|
||||
_(InitElemGetterSetter) \
|
||||
|
@ -183,6 +183,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
||||
CUSTOM_OP(NewArray)
|
||||
CUSTOM_OP(NewObject)
|
||||
CUSTOM_OP(NewCallObject)
|
||||
CUSTOM_OP(NewRunOnceCallObject)
|
||||
CUSTOM_OP(NewDerivedTypedObject)
|
||||
UNSAFE_OP(InitElem)
|
||||
UNSAFE_OP(InitElemGetterSetter)
|
||||
@ -531,6 +532,13 @@ ParallelSafetyVisitor::visitNewCallObject(MNewCallObject *ins)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ParallelSafetyVisitor::visitNewRunOnceCallObject(MNewRunOnceCallObject *ins)
|
||||
{
|
||||
replace(ins, MNewCallObjectPar::New(alloc(), ForkJoinContext(), ins));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ParallelSafetyVisitor::visitLambda(MLambda *ins)
|
||||
{
|
||||
|
@ -525,10 +525,9 @@ NewSlots(JSRuntime *rt, unsigned nslots)
|
||||
}
|
||||
|
||||
JSObject *
|
||||
NewCallObject(JSContext *cx, HandleScript script,
|
||||
HandleShape shape, HandleTypeObject type, HeapSlot *slots)
|
||||
NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots)
|
||||
{
|
||||
JSObject *obj = CallObject::create(cx, script, shape, type, slots);
|
||||
JSObject *obj = CallObject::create(cx, shape, type, slots);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
@ -543,6 +542,25 @@ NewCallObject(JSContext *cx, HandleScript script,
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
NewSingletonCallObject(JSContext *cx, HandleShape shape, HeapSlot *slots)
|
||||
{
|
||||
JSObject *obj = CallObject::createSingleton(cx, shape, slots);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
// The JIT creates call objects in the nursery, so elides barriers for
|
||||
// the initializing writes. The interpreter, however, may have allocated
|
||||
// the call object tenured, so barrier as needed before re-entering.
|
||||
MOZ_ASSERT(!IsInsideNursery(cx->runtime(), obj),
|
||||
"singletons are created in the tenured heap");
|
||||
cx->runtime()->gcStoreBuffer.putWholeCell(obj);
|
||||
#endif
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
NewStringObject(JSContext *cx, HandleString str)
|
||||
{
|
||||
|
@ -618,8 +618,8 @@ bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Handl
|
||||
bool InterruptCheck(JSContext *cx);
|
||||
|
||||
HeapSlot *NewSlots(JSRuntime *rt, unsigned nslots);
|
||||
JSObject *NewCallObject(JSContext *cx, HandleScript script,
|
||||
HandleShape shape, HandleTypeObject type, HeapSlot *slots);
|
||||
JSObject *NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots);
|
||||
JSObject *NewSingletonCallObject(JSContext *cx, HandleShape shape, HeapSlot *slots);
|
||||
JSObject *NewStringObject(JSContext *cx, HandleString str);
|
||||
|
||||
bool SPSEnter(JSContext *cx, HandleScript script);
|
||||
|
@ -136,28 +136,39 @@ ScopeObject::setEnclosingScope(HandleObject obj)
|
||||
setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(*obj));
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a bare-bones call object given a shape, type, and slots pointer.
|
||||
* The call object must be further initialized to be usable.
|
||||
*/
|
||||
CallObject *
|
||||
CallObject::create(JSContext *cx, HandleScript script, HandleShape shape, HandleTypeObject type, HeapSlot *slots)
|
||||
CallObject::create(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots)
|
||||
{
|
||||
MOZ_ASSERT(!type->singleton(),
|
||||
"passed a singleton type to create() (use createSingleton() "
|
||||
"instead)");
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
|
||||
JS_ASSERT(CanBeFinalizedInBackground(kind, &CallObject::class_));
|
||||
MOZ_ASSERT(CanBeFinalizedInBackground(kind, &CallObject::class_));
|
||||
kind = gc::GetBackgroundAllocKind(kind);
|
||||
|
||||
gc::InitialHeap heap = script->treatAsRunOnce() ? gc::TenuredHeap : gc::DefaultHeap;
|
||||
JSObject *obj = JSObject::create(cx, kind, heap, shape, type, slots);
|
||||
JSObject *obj = JSObject::create(cx, kind, gc::DefaultHeap, shape, type, slots);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
if (script->treatAsRunOnce()) {
|
||||
RootedObject nobj(cx, obj);
|
||||
if (!JSObject::setSingletonType(cx, nobj))
|
||||
return nullptr;
|
||||
return &nobj->as<CallObject>();
|
||||
}
|
||||
return &obj->as<CallObject>();
|
||||
}
|
||||
|
||||
CallObject *
|
||||
CallObject::createSingleton(JSContext *cx, HandleShape shape, HeapSlot *slots)
|
||||
{
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
|
||||
MOZ_ASSERT(CanBeFinalizedInBackground(kind, &CallObject::class_));
|
||||
kind = gc::GetBackgroundAllocKind(kind);
|
||||
|
||||
RootedTypeObject type(cx, cx->getSingletonType(&class_, nullptr));
|
||||
if (!type)
|
||||
return nullptr;
|
||||
RootedObject obj(cx, JSObject::create(cx, kind, gc::TenuredHeap, shape, type, slots));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(obj->hasSingletonType(),
|
||||
"type created inline above must be a singleton");
|
||||
|
||||
return &obj->as<CallObject>();
|
||||
}
|
||||
|
@ -236,8 +236,22 @@ class CallObject : public ScopeObject
|
||||
static const Class class_;
|
||||
|
||||
/* These functions are internal and are exposed only for JITs. */
|
||||
|
||||
/*
|
||||
* Construct a bare-bones call object given a shape, a non-singleton type,
|
||||
* and slots pointer. The call object must be further initialized to be
|
||||
* usable.
|
||||
*/
|
||||
static CallObject *
|
||||
create(JSContext *cx, HandleScript script, HandleShape shape, HandleTypeObject type, HeapSlot *slots);
|
||||
create(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots);
|
||||
|
||||
/*
|
||||
* Construct a bare-bones call object given a shape and slots pointer, and
|
||||
* make it have singleton type. The call object must be initialized to be
|
||||
* usable.
|
||||
*/
|
||||
static CallObject *
|
||||
createSingleton(JSContext *cx, HandleShape shape, HeapSlot *slots);
|
||||
|
||||
static CallObject *
|
||||
createTemplateObject(JSContext *cx, HandleScript script, gc::InitialHeap heap);
|
||||
|
Loading…
Reference in New Issue
Block a user