Bug 1311294 - wasm baseline, check register sets against leaks. r=bbouvier
authorLars T Hansen <lhansen@mozilla.com>
Tue, 07 Feb 2017 17:20:06 +0100
changeset 341191 3bd986e5c3c856b81a5b09fdd69925555ec5a93f
parent 341190 e2b893be9f4ca14fe0b96080092d9b19b46b5d70
child 341192 47a77e19ab85bff095a5bae30b1c78c62fc6e631
push id86661
push userlhansen@mozilla.com
push dateTue, 07 Feb 2017 20:37:55 +0000
treeherdermozilla-inbound@3bd986e5c3c8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs1311294
milestone54.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 1311294 - wasm baseline, check register sets against leaks. r=bbouvier
js/src/wasm/WasmBaselineCompile.cpp
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -496,19 +496,21 @@ class BaseCompiler
     ValType                     latentType_;     // Operand type, if latentOp_ is true
     Assembler::Condition        latentIntCmp_;   // Comparison operator, if latentOp_ == Compare, int types
     Assembler::DoubleCondition  latentDoubleCmp_;// Comparison operator, if latentOp_ == Compare, float types
 
     FuncOffsets                 offsets_;
     MacroAssembler&             masm;            // No '_' suffix - too tedious...
 
     AllocatableGeneralRegisterSet availGPR_;
-    AllocatableFloatRegisterSet availFPU_;
+    AllocatableFloatRegisterSet   availFPU_;
 #ifdef DEBUG
-    bool                        scratchRegisterTaken_;
+    bool                          scratchRegisterTaken_;
+    AllocatableGeneralRegisterSet allGPR_;       // The registers available to the compiler
+    AllocatableFloatRegisterSet   allFPU_;       //   after removing ScratchReg, HeapReg, etc
 #endif
 
     Vector<Local, 8, SystemAllocPolicy> localInfo_;
     Vector<OutOfLineCode*, 8, SystemAllocPolicy> outOfLine_;
 
     // Index into localInfo_ of the special local used for saving the TLS
     // pointer. This follows the function's real arguments and locals.
     uint32_t                    tlsSlot_;
@@ -2023,16 +2025,60 @@ class BaseCompiler
     }
 
     // Peek at the stack, for calls.
 
     Stk& peek(uint32_t relativeDepth) {
         return stk_[stk_.length()-1-relativeDepth];
     }
 
+#ifdef DEBUG
+    // Check that we're not leaking registers by comparing the
+    // state of the stack + available registers with the set of
+    // all available registers.
+
+    // Call this before compiling any code.
+    void setupRegisterLeakCheck() {
+        allGPR_ = availGPR_;
+        allFPU_ = availFPU_;
+    }
+
+    // Call this between opcodes.
+    void performRegisterLeakCheck() {
+        AllocatableGeneralRegisterSet knownGPR_ = availGPR_;
+        AllocatableFloatRegisterSet knownFPU_ = availFPU_;
+        for (size_t i = 0 ; i < stk_.length() ; i++) {
+	    Stk& item = stk_[i];
+	    switch (item.kind_) {
+	      case Stk::RegisterI32:
+		knownGPR_.add(item.i32reg());
+		break;
+	      case Stk::RegisterI64:
+#ifdef JS_PUNBOX64
+		knownGPR_.add(item.i64reg().reg);
+#else
+		knownGPR_.add(item.i64reg().high);
+		knownGPR_.add(item.i64reg().low);
+#endif
+		break;
+	      case Stk::RegisterF32:
+		knownFPU_.add(item.f32reg());
+		break;
+	      case Stk::RegisterF64:
+		knownFPU_.add(item.f64reg());
+		break;
+	      default:
+		break;
+	    }
+	}
+	MOZ_ASSERT(knownGPR_.bits() == allGPR_.bits());
+	MOZ_ASSERT(knownFPU_.bits() == allFPU_.bits());
+    }
+#endif
+
     ////////////////////////////////////////////////////////////
     //
     // Control stack
 
     void initControl(Control& item)
     {
         // Make sure the constructor was run properly
         MOZ_ASSERT(item.framePushed == UINT32_MAX && item.stackSize == UINT32_MAX);
@@ -6621,16 +6667,20 @@ bool
 BaseCompiler::emitBody()
 {
     uint32_t overhead = 0;
 
     for (;;) {
 
         Nothing unused_a, unused_b;
 
+#ifdef DEBUG
+        performRegisterLeakCheck();
+#endif
+
 #define emitBinary(doEmit, type) \
         iter_.readBinary(type, &unused_a, &unused_b) && (deadCode_ || (doEmit(), true))
 
 #define emitUnary(doEmit, type) \
         iter_.readUnary(type, &unused_a) && (deadCode_ || (doEmit(), true))
 
 #define emitComparison(doEmit, operandType, compareOp) \
         iter_.readComparison(operandType, &unused_a, &unused_b) && \
@@ -7362,16 +7412,20 @@ BaseCompiler::BaseCompiler(const ModuleE
 #elif defined(JS_CODEGEN_ARM64)
     availGPR_.take(HeapReg);
     availGPR_.take(HeapLenReg);
 #elif defined(JS_CODEGEN_X86)
     availGPR_.take(ScratchRegX86);
 #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
     availGPR_.take(HeapReg);
 #endif
+
+#ifdef DEBUG
+    setupRegisterLeakCheck();
+#endif
 }
 
 bool
 BaseCompiler::init()
 {
     if (!SigD_.append(ValType::F64))
         return false;
     if (!SigF_.append(ValType::F32))