Bug 977577 - IonMonkey: Improve MRecompilecheck by checking if already recompiling, before doing vmcall, r=jandem
authorHannes Verschore <hv1989@gmail.com>
Mon, 10 Mar 2014 12:07:35 +0100
changeset 172770 74d0e18037f5cc64a3d480d66de873784ae00e0c
parent 172769 fb23f20f9c6cdebb4a674851bb4cff1c100c5b63
child 172771 64e41faa2462a8388fbbd42a2a0f61a1ece0492d
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjandem
bugs977577
milestone30.0a1
Bug 977577 - IonMonkey: Improve MRecompilecheck by checking if already recompiling, before doing vmcall, r=jandem
js/src/jit/CodeGenerator.cpp
js/src/jit/CodeGenerator.h
js/src/jit/IonCode.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -140,19 +140,17 @@ CodeGenerator::visitOutOfLineCache(OutOf
 
 StringObject *
 MNewStringObject::templateObj() const {
     return &templateObj_->as<StringObject>();
 }
 
 CodeGenerator::CodeGenerator(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
   : CodeGeneratorSpecific(gen, graph, masm)
-#ifdef DEBUG
   , ionScriptLabels_(gen->alloc())
-#endif
   , unassociatedScriptCounts_(nullptr)
 {
 }
 
 CodeGenerator::~CodeGenerator()
 {
     JS_ASSERT_IF(!gen->compilingAsmJS(), masm.numAsmJSAbsoluteLinks() == 0);
     js_delete(unassociatedScriptCounts_);
@@ -6267,24 +6265,22 @@ CodeGenerator::link(JSContext *cx, types
 
     ionScript->setDeoptTable(deoptTable_);
 
 #if defined(JS_ION_PERF)
     if (PerfEnabled())
         perfSpewer_.writeProfile(script, code, masm);
 #endif
 
-#ifdef DEBUG
     for (size_t i = 0; i < ionScriptLabels_.length(); i++) {
         ionScriptLabels_[i].fixup(&masm);
         Assembler::patchDataWithValueCheck(CodeLocationLabel(code, ionScriptLabels_[i]),
                                            ImmPtr(ionScript),
                                            ImmPtr((void*)-1));
     }
-#endif
 
     // for generating inline caches during the execution.
     if (runtimeData_.length())
         ionScript->copyRuntimeData(&runtimeData_[0]);
     if (cacheList_.length())
         ionScript->copyCacheEntries(&cacheList_[0], masm);
 
     // for marking during GC.
@@ -8259,23 +8255,34 @@ CodeGenerator::visitAssertRangeV(LAssert
 }
 
 typedef bool (*RecompileFn)(JSContext *);
 static const VMFunction RecompileFnInfo = FunctionInfo<RecompileFn>(Recompile);
 
 bool
 CodeGenerator::visitRecompileCheck(LRecompileCheck *ins)
 {
-    Register useCount = ToRegister(ins->scratch());
-
-    masm.movePtr(ImmPtr(ins->mir()->script()->addressOfUseCount()), useCount);
-    Address ptr(useCount, 0);
-    masm.add32(Imm32(1), ptr);
-
-    OutOfLineCode *ool = oolCallVM(RecompileFnInfo, ins, (ArgList()), StoreRegisterTo(useCount));
-    masm.branch32(Assembler::Above, ptr, Imm32(ins->mir()->useCount()), ool->entry());
+    Label done;
+    Register tmp = ToRegister(ins->scratch());
+    OutOfLineCode *ool = oolCallVM(RecompileFnInfo, ins, (ArgList()), StoreRegisterTo(tmp));
+
+    // Check if usecount is high enough.
+    masm.movePtr(ImmPtr(ins->mir()->script()->addressOfUseCount()), tmp);
+    Address ptr(tmp, 0);
+    masm.add32(Imm32(1), tmp);
+    masm.branch32(Assembler::BelowOrEqual, ptr, Imm32(ins->mir()->useCount()), &done);
+
+    // Check if not yet recompiling.
+    CodeOffsetLabel label = masm.movWithPatch(ImmWord(uintptr_t(-1)), tmp);
+    if (!ionScriptLabels_.append(label))
+        return false;
+    masm.branch32(Assembler::Equal,
+                  Address(tmp, IonScript::offsetOfRecompiling()),
+                  Imm32(0),
+                  ool->entry());
     masm.bind(ool->rejoin());
+    masm.bind(&done);
 
     return true;
 }
 
 } // namespace jit
 } // namespace js
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -435,18 +435,18 @@ class CodeGenerator : public CodeGenerat
     Label *getJumpLabelForBranch(MBasicBlock *block);
 
     // Bailout if an element about to be written to is a hole.
     bool emitStoreHoleCheck(Register elements, const LAllocation *index, LSnapshot *snapshot);
 
     bool emitAssertRangeI(const Range *r, Register input);
     bool emitAssertRangeD(const Range *r, FloatRegister input, FloatRegister temp);
 
+    Vector<CodeOffsetLabel, 0, IonAllocPolicy> ionScriptLabels_;
 #ifdef DEBUG
-    Vector<CodeOffsetLabel, 0, IonAllocPolicy> ionScriptLabels_;
     bool branchIfInvalidated(Register temp, Label *invalidated);
 
     bool emitDebugResultChecks(LInstruction *ins);
     bool emitObjectOrStringResultChecks(LInstruction *lir, MDefinition *mir);
     bool emitValueResultChecks(LInstruction *lir, MDefinition *mir);
 #endif
 
     // Script counts created when compiling code with no associated JSScript.
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -189,17 +189,17 @@ struct IonScript
     // targets is not compiled.  Used in ForkJoin.cpp to decide when
     // we should add call targets to the worklist.
     mozilla::Atomic<bool, mozilla::Relaxed> hasUncompiledCallTarget_;
 
     // Flag set if IonScript was compiled with SPS profiling enabled.
     bool hasSPSInstrumentation_;
 
     // Flag for if this script is getting recompiled.
-    bool recompiling_;
+    uint32_t recompiling_;
 
     // Any kind of data needed by the runtime, these can be either cache
     // information or profiling info.
     uint32_t runtimeData_;
     uint32_t runtimeSize_;
 
     // State for polymorphic caches in the compiled code. All caches are stored
     // in the runtimeData buffer and indexed by the cacheIndex which give a
@@ -342,16 +342,19 @@ struct IonScript
         return offsetof(IonScript, osrEntryOffset_);
     }
     static inline size_t offsetOfSkipArgCheckEntryOffset() {
         return offsetof(IonScript, skipArgCheckEntryOffset_);
     }
     static inline size_t offsetOfRefcount() {
         return offsetof(IonScript, refcount_);
     }
+    static inline size_t offsetOfRecompiling() {
+        return offsetof(IonScript, recompiling_);
+    }
 
   public:
     JitCode *method() const {
         return method_;
     }
     void setMethod(JitCode *code) {
         JS_ASSERT(!invalidated());
         method_ = code;