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 172722 74d0e18037f5cc64a3d480d66de873784ae00e0c
parent 172721 fb23f20f9c6cdebb4a674851bb4cff1c100c5b63
child 172723 64e41faa2462a8388fbbd42a2a0f61a1ece0492d
push id40815
push userhv1989@gmail.com
push dateMon, 10 Mar 2014 11:08:15 +0000
treeherdermozilla-inbound@74d0e18037f5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs977577
milestone30.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 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;