Bug 1135039: Implement LVariadicInstruction; r=sunfish
--- a/js/src/jit/LIR.h
+++ b/js/src/jit/LIR.h
@@ -8,16 +8,17 @@
#define jit_LIR_h
// This file declares the core data structures for LIR: storage allocations for
// inputs and outputs, as well as the interface instructions must conform to.
#include "mozilla/Array.h"
#include "jit/Bailouts.h"
+#include "jit/FixedList.h"
#include "jit/InlineList.h"
#include "jit/JitAllocPolicy.h"
#include "jit/LOpcodes.h"
#include "jit/MIR.h"
#include "jit/MIRGraph.h"
#include "jit/Registers.h"
#include "jit/Safepoints.h"
@@ -1057,16 +1058,75 @@ class LInstructionHelper : public LInstr
return getOperand(0);
}
const LDefinition *output() {
MOZ_ASSERT(numDefs() == 1);
return getDef(0);
}
};
+template<size_t Defs, size_t Temps>
+class LVariadicInstruction : public LInstruction
+{
+ mozilla::Array<LDefinition, Defs> defs_;
+ FixedList<LAllocation> operands_;
+ mozilla::Array<LDefinition, Temps> temps_;
+
+ public:
+ bool init(TempAllocator &alloc, size_t length) {
+ return operands_.init(alloc, length);
+ }
+
+ size_t numDefs() const MOZ_FINAL MOZ_OVERRIDE {
+ return Defs;
+ }
+ LDefinition *getDef(size_t index) MOZ_FINAL MOZ_OVERRIDE {
+ return &defs_[index];
+ }
+ size_t numOperands() const MOZ_FINAL MOZ_OVERRIDE {
+ return operands_.length();
+ }
+ LAllocation *getOperand(size_t index) MOZ_FINAL MOZ_OVERRIDE {
+ return &operands_[index];
+ }
+ size_t numTemps() const MOZ_FINAL MOZ_OVERRIDE {
+ return Temps;
+ }
+ LDefinition *getTemp(size_t index) MOZ_FINAL MOZ_OVERRIDE {
+ return &temps_[index];
+ }
+
+ void setDef(size_t index, const LDefinition &def) MOZ_FINAL MOZ_OVERRIDE {
+ defs_[index] = def;
+ }
+ void setOperand(size_t index, const LAllocation &a) MOZ_FINAL MOZ_OVERRIDE {
+ operands_[index] = a;
+ }
+ void setTemp(size_t index, const LDefinition &a) MOZ_FINAL MOZ_OVERRIDE {
+ temps_[index] = a;
+ }
+
+ size_t numSuccessors() const MOZ_OVERRIDE {
+ return 0;
+ }
+ MBasicBlock *getSuccessor(size_t i) const MOZ_OVERRIDE {
+ MOZ_ASSERT(false);
+ return nullptr;
+ }
+ void setSuccessor(size_t i, MBasicBlock *successor) MOZ_OVERRIDE {
+ MOZ_ASSERT(false);
+ }
+
+ // Default accessors, assuming a single input and output, respectively.
+ const LDefinition *output() {
+ MOZ_ASSERT(numDefs() == 1);
+ return getDef(0);
+ }
+};
+
template <size_t Defs, size_t Operands, size_t Temps>
class LCallInstructionHelper : public LInstructionHelper<Defs, Operands, Temps>
{
public:
virtual bool isCall() const {
return true;
}
};
--- a/js/src/jit/shared/Lowering-shared-inl.h
+++ b/js/src/jit/shared/Lowering-shared-inl.h
@@ -30,16 +30,40 @@ LIRGeneratorShared::use(MDefinition *mir
#if BOX_PIECES > 1
MOZ_ASSERT(mir->type() != MIRType_Value);
#endif
ensureDefined(mir);
policy.setVirtualRegister(mir->virtualRegister());
return policy;
}
+template <size_t X> void
+LIRGeneratorShared::define(LVariadicInstruction<1, X> *lir, MDefinition *mir, const LDefinition &def)
+{
+ // Call instructions should use defineReturn.
+ MOZ_ASSERT(!lir->isCall());
+
+ uint32_t vreg = getVirtualRegister();
+
+ // Assign the definition and a virtual register. Then, propagate this
+ // virtual register to the MIR, so we can map MIR to LIR during lowering.
+ lir->setDef(0, def);
+ lir->getDef(0)->setVirtualRegister(vreg);
+ lir->setMir(mir);
+ mir->setVirtualRegister(vreg);
+ add(lir);
+}
+
+template <size_t X> void
+LIRGeneratorShared::define(LVariadicInstruction<1, X> *lir, MDefinition *mir, LDefinition::Policy policy)
+{
+ LDefinition::Type type = LDefinition::TypeFrom(mir->type());
+ define(lir, mir, LDefinition(type, policy));
+}
+
template <size_t X, size_t Y> void
LIRGeneratorShared::define(LInstructionHelper<1, X, Y> *lir, MDefinition *mir, const LDefinition &def)
{
// Call instructions should use defineReturn.
MOZ_ASSERT(!lir->isCall());
uint32_t vreg = getVirtualRegister();
--- a/js/src/jit/shared/Lowering-shared.h
+++ b/js/src/jit/shared/Lowering-shared.h
@@ -140,16 +140,23 @@ class LIRGeneratorShared : public MDefin
const LAllocation &output);
template <size_t Ops, size_t Temps>
inline void defineBox(LInstructionHelper<BOX_PIECES, Ops, Temps> *lir, MDefinition *mir,
LDefinition::Policy policy = LDefinition::REGISTER);
inline void defineReturn(LInstruction *lir, MDefinition *mir);
+ template <size_t X>
+ inline void define(LVariadicInstruction<1, X> *lir, MDefinition *mir, const LDefinition &def);
+
+ template <size_t X>
+ inline void define(LVariadicInstruction<1, X> *lir, MDefinition *mir,
+ LDefinition::Policy policy = LDefinition::REGISTER);
+
template <size_t Ops, size_t Temps>
inline void define(LInstructionHelper<1, Ops, Temps> *lir, MDefinition *mir,
const LDefinition &def);
template <size_t Ops, size_t Temps>
inline void define(LInstructionHelper<1, Ops, Temps> *lir, MDefinition *mir,
LDefinition::Policy policy = LDefinition::REGISTER);