Bug 1272269: IonMonkey - Reintroduce template object on the VM variant of MNewArray And MNewObject, r=efaust
authorHannes Verschore <hv1989@gmail.com>
Fri, 13 May 2016 23:52:30 +0200
changeset 297423 ac69d4a75d6c8c3d0854f35c21a3f0621ad9fcde
parent 297422 229198fdc3320d64ef720dc6368e95fc39d96718
child 297424 bd21c16b035a5f4d79ac2cd15d35260e528e910e
push id30257
push userphilringnalda@gmail.com
push dateSat, 14 May 2016 20:03:55 +0000
treeherdermozilla-central@1665c708ebab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersefaust
bugs1272269
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1272269: IonMonkey - Reintroduce template object on the VM variant of MNewArray And MNewObject, r=efaust
js/src/jit/CodeGenerator.cpp
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
js/src/jit/MIR.cpp
js/src/jit/MIR.h
js/src/jit/shared/LIR-shared.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -5181,17 +5181,17 @@ CodeGenerator::visitNewArray(LNewArray* 
 {
     Register objReg = ToRegister(lir->output());
     Register tempReg = ToRegister(lir->temp());
     JSObject* templateObject = lir->mir()->templateObject();
     DebugOnly<uint32_t> length = lir->mir()->length();
 
     MOZ_ASSERT(length <= NativeObject::MAX_DENSE_ELEMENTS_COUNT);
 
-    if (!templateObject) {
+    if (lir->mir()->isVMCall()) {
         visitNewArrayCallVM(lir);
         return;
     }
 
     OutOfLineNewArray* ool = new(alloc()) OutOfLineNewArray(lir);
     addOutOfLineCode(ool, lir->mir());
 
     masm.createGCObject(objReg, tempReg, templateObject, lir->mir()->initialHeap(),
@@ -5438,17 +5438,17 @@ ShouldInitFixedSlots(LInstruction* lir, 
 
 void
 CodeGenerator::visitNewObject(LNewObject* lir)
 {
     Register objReg = ToRegister(lir->output());
     Register tempReg = ToRegister(lir->temp());
     JSObject* templateObject = lir->mir()->templateObject();
 
-    if (!templateObject) {
+    if (lir->mir()->isVMCall()) {
         visitNewObjectVMCall(lir);
         return;
     }
 
     OutOfLineNewObject* ool = new(alloc()) OutOfLineNewObject(lir);
     addOutOfLineCode(ool, lir->mir());
 
     bool initContents = ShouldInitFixedSlots(lir, templateObject);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -7267,27 +7267,33 @@ IonBuilder::newArrayTrySharedStub(bool* 
     if (!resumeAfter(stub))
         return false;
 
     *emitted = true;
     return true;
 }
 
 bool
-IonBuilder::newArrayTryVM(bool* emitted, uint32_t length)
+IonBuilder::newArrayTryVM(bool* emitted, JSObject* templateObject, uint32_t length)
 {
     MOZ_ASSERT(*emitted == false);
 
     // Emit a VM call.
 
     gc::InitialHeap heap = gc::DefaultHeap;
     MConstant* templateConst = MConstant::New(alloc(), NullValue());
+
+    if (templateObject) {
+        heap = templateObject->group()->initialHeap(constraints());
+        templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
+    }
+
     current->add(templateConst);
 
-    MNewArray* ins = MNewArray::New(alloc(), constraints(), length, templateConst, heap, pc);
+    MNewArray* ins = MNewArray::NewVM(alloc(), constraints(), length, templateConst, heap, pc);
     current->add(ins);
     current->push(ins);
 
     *emitted = true;
     return true;
 }
 
 bool
@@ -7315,17 +7321,17 @@ IonBuilder::jsop_newarray(JSObject* temp
     if (!forceInlineCaches()) {
         if (!newArrayTryTemplateObject(&emitted, templateObject, length) || emitted)
             return emitted;
     }
 
     if (!newArrayTrySharedStub(&emitted) || emitted)
         return emitted;
 
-    if (!newArrayTryVM(&emitted, length) || emitted)
+    if (!newArrayTryVM(&emitted, templateObject, length) || emitted)
         return emitted;
 
     MOZ_CRASH("newarray should have been emited");
 }
 
 bool
 IonBuilder::jsop_newarray_copyonwrite()
 {
@@ -7399,50 +7405,58 @@ IonBuilder::newObjectTrySharedStub(bool*
     if (!resumeAfter(stub))
         return false;
 
     *emitted = true;
     return true;
 }
 
 bool
-IonBuilder::newObjectTryVM(bool* emitted)
+IonBuilder::newObjectTryVM(bool* emitted, JSObject* templateObject)
 {
     // Emit a VM call.
+    MOZ_ASSERT(JSOp(*pc) == JSOP_NEWOBJECT || JSOp(*pc) == JSOP_NEWINIT);
 
     gc::InitialHeap heap = gc::DefaultHeap;
     MConstant* templateConst = MConstant::New(alloc(), NullValue());
+
+    if (templateObject) {
+        heap = templateObject->group()->initialHeap(constraints());
+        templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
+    }
+
     current->add(templateConst);
 
-    MNewObject* ins = MNewObject::New(alloc(), constraints(), templateConst, heap,
-                                     MNewObject::ObjectLiteral);
+    MNewObject* ins = MNewObject::NewVM(alloc(), constraints(), templateConst, heap,
+                                        MNewObject::ObjectLiteral);
     current->add(ins);
     current->push(ins);
 
     if (!resumeAfter(ins))
         return false;
 
     *emitted = true;
     return true;
 }
 
 bool
 IonBuilder::jsop_newobject()
 {
     bool emitted = false;
 
+    JSObject* templateObject = inspector->getTemplateObject(pc);
+
     if (!forceInlineCaches()) {
-        JSObject* templateObject = inspector->getTemplateObject(pc);
         if (!newObjectTryTemplateObject(&emitted, templateObject) || emitted)
             return emitted;
     }
     if (!newObjectTrySharedStub(&emitted) || emitted)
         return emitted;
 
-    if (!newObjectTryVM(&emitted) || emitted)
+    if (!newObjectTryVM(&emitted, templateObject) || emitted)
         return emitted;
 
     MOZ_CRASH("newobject should have been emited");
 }
 
 bool
 IonBuilder::jsop_initelem()
 {
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -525,22 +525,22 @@ class IonBuilder
                                                                MDefinition* right);
     MOZ_MUST_USE bool compareTrySharedStub(bool* emitted, JSOp op, MDefinition* left,
                                            MDefinition* right);
 
     // jsop_newarray helpers.
     MOZ_MUST_USE bool newArrayTrySharedStub(bool* emitted);
     MOZ_MUST_USE bool newArrayTryTemplateObject(bool* emitted, JSObject* templateObject,
                                                 uint32_t length);
-    MOZ_MUST_USE bool newArrayTryVM(bool* emitted, uint32_t length);
+    MOZ_MUST_USE bool newArrayTryVM(bool* emitted, JSObject* templateObject, uint32_t length);
 
     // jsop_newobject helpers.
     MOZ_MUST_USE bool newObjectTrySharedStub(bool* emitted);
     MOZ_MUST_USE bool newObjectTryTemplateObject(bool* emitted, JSObject* templateObject);
-    MOZ_MUST_USE bool newObjectTryVM(bool* emitted);
+    MOZ_MUST_USE bool newObjectTryVM(bool* emitted, JSObject* templateObject);
 
     // jsop_in helpers.
     MOZ_MUST_USE bool inTryDense(bool* emitted, MDefinition* obj, MDefinition* id);
     MOZ_MUST_USE bool inTryFold(bool* emitted, MDefinition* obj, MDefinition* id);
 
     // binary data lookup helpers.
     TypedObjectPrediction typedObjectPrediction(MDefinition* typedObj);
     TypedObjectPrediction typedObjectPrediction(TemporaryTypeSet* types);
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -4601,22 +4601,23 @@ MArrayState::Copy(TempAllocator& alloc, 
     if (!res || !res->init(alloc, arr, len))
         return nullptr;
     for (size_t i = 0; i < res->numElements(); i++)
         res->initElement(i, state->getElement(i));
     return res;
 }
 
 MNewArray::MNewArray(CompilerConstraintList* constraints, uint32_t length, MConstant* templateConst,
-                     gc::InitialHeap initialHeap, jsbytecode* pc)
+                     gc::InitialHeap initialHeap, jsbytecode* pc, bool vmCall)
   : MUnaryInstruction(templateConst),
     length_(length),
     initialHeap_(initialHeap),
     convertDoubleElements_(false),
-    pc_(pc)
+    pc_(pc),
+    vmCall_(vmCall)
 {
     setResultType(MIRType::Object);
     if (templateObject()) {
         if (TemporaryTypeSet* types = MakeSingletonTypeSet(constraints, templateObject())) {
             setResultTypeSet(types);
             if (types->convertDoubleElements(constraints) == TemporaryTypeSet::AlwaysConvertToDoubles)
                 convertDoubleElements_ = true;
         }
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3108,27 +3108,36 @@ class MNewArray
     // Heap where the array should be allocated.
     gc::InitialHeap initialHeap_;
 
     // Whether values written to this array should be converted to double first.
     bool convertDoubleElements_;
 
     jsbytecode* pc_;
 
+    bool vmCall_;
+
     MNewArray(CompilerConstraintList* constraints, uint32_t length, MConstant* templateConst,
-              gc::InitialHeap initialHeap, jsbytecode* pc);
+              gc::InitialHeap initialHeap, jsbytecode* pc, bool vmCall);
 
   public:
     INSTRUCTION_HEADER(NewArray)
 
     static MNewArray* New(TempAllocator& alloc, CompilerConstraintList* constraints,
                           uint32_t length, MConstant* templateConst,
                           gc::InitialHeap initialHeap, jsbytecode* pc)
     {
-        return new(alloc) MNewArray(constraints, length, templateConst, initialHeap, pc);
+        return new(alloc) MNewArray(constraints, length, templateConst, initialHeap, pc, false);
+    }
+
+    static MNewArray* NewVM(TempAllocator& alloc, CompilerConstraintList* constraints,
+                            uint32_t length, MConstant* templateConst,
+                            gc::InitialHeap initialHeap, jsbytecode* pc)
+    {
+        return new(alloc) MNewArray(constraints, length, templateConst, initialHeap, pc, true);
     }
 
     uint32_t length() const {
         return length_;
     }
 
     JSObject* templateObject() const {
         return getOperand(0)->toConstant()->toObjectOrNull();
@@ -3137,16 +3146,20 @@ class MNewArray
     gc::InitialHeap initialHeap() const {
         return initialHeap_;
     }
 
     jsbytecode* pc() const {
         return pc_;
     }
 
+    bool isVMCall() const {
+        return vmCall_;
+    }
+
     bool convertDoubleElements() const {
         return convertDoubleElements_;
     }
 
     // NewArray is marked as non-effectful because all our allocations are
     // either lazy when we are using "new Array(length)" or bounded by the
     // script or the stack size when we are using "new Array(...)" or "[...]"
     // notations.  So we might have to allocate the array twice if we bail
@@ -3252,22 +3265,24 @@ class MNewObject
     public NoTypePolicy::Data
 {
   public:
     enum Mode { ObjectLiteral, ObjectCreate };
 
   private:
     gc::InitialHeap initialHeap_;
     Mode mode_;
+    bool vmCall_;
 
     MNewObject(CompilerConstraintList* constraints, MConstant* templateConst,
-               gc::InitialHeap initialHeap, Mode mode)
+               gc::InitialHeap initialHeap, Mode mode, bool vmCall)
       : MUnaryInstruction(templateConst),
         initialHeap_(initialHeap),
-        mode_(mode)
+        mode_(mode),
+        vmCall_(vmCall)
     {
         MOZ_ASSERT_IF(mode != ObjectLiteral, templateObject());
         setResultType(MIRType::Object);
 
         if (JSObject* obj = templateObject())
             setResultTypeSet(MakeSingletonTypeSet(constraints, obj));
 
         // The constant is kept separated in a MConstant, this way we can safely
@@ -3281,31 +3296,42 @@ class MNewObject
 
   public:
     INSTRUCTION_HEADER(NewObject)
 
     static MNewObject* New(TempAllocator& alloc, CompilerConstraintList* constraints,
                            MConstant* templateConst, gc::InitialHeap initialHeap,
                            Mode mode)
     {
-        return new(alloc) MNewObject(constraints, templateConst, initialHeap, mode);
+        return new(alloc) MNewObject(constraints, templateConst, initialHeap, mode, false);
+    }
+
+    static MNewObject* NewVM(TempAllocator& alloc, CompilerConstraintList* constraints,
+                             MConstant* templateConst, gc::InitialHeap initialHeap,
+                             Mode mode)
+    {
+        return new(alloc) MNewObject(constraints, templateConst, initialHeap, mode, true);
     }
 
     Mode mode() const {
         return mode_;
     }
 
     JSObject* templateObject() const {
         return getOperand(0)->toConstant()->toObjectOrNull();
     }
 
     gc::InitialHeap initialHeap() const {
         return initialHeap_;
     }
 
+    bool isVMCall() const {
+        return vmCall_;
+    }
+
     bool writeRecoverData(CompactBufferWriter& writer) const override;
     bool canRecoverOnBailout() const override {
         // The template object can safely be used in the recover instruction
         // because it can never be mutated by any other function execution.
         return templateObject() != nullptr;
     }
 };
 
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -869,17 +869,17 @@ class LNewArray : public LInstructionHel
   public:
     LIR_HEADER(NewArray)
 
     explicit LNewArray(const LDefinition& temp) {
         setTemp(0, temp);
     }
 
     const char* extraName() const {
-        return mir()->templateObject() ? "VMCall" : nullptr;
+        return mir()->isVMCall() ? "VMCall" : nullptr;
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
     MNewArray* mir() const {
         return mir_->toNewArray();
@@ -931,17 +931,17 @@ class LNewObject : public LInstructionHe
   public:
     LIR_HEADER(NewObject)
 
     explicit LNewObject(const LDefinition& temp) {
         setTemp(0, temp);
     }
 
     const char* extraName() const {
-        return mir()->templateObject() ? "VMCall" : nullptr;
+        return mir()->isVMCall() ? "VMCall" : nullptr;
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
     MNewObject* mir() const {
         return mir_->toNewObject();