Bug 1277973 - Baldr: prepare CallSiteAndTarget for another Kind (r=bbouvier)
authorLuke Wagner <luke@mozilla.com>
Thu, 13 Oct 2016 13:17:55 -0500
changeset 317901 e29daffaaca4b5a22756d631eac82d920a701c62
parent 317900 e6d2b67b35e5d0d48949b05c9599b892cf70ba68
child 317902 33b295d58244ce40eda37a5ce57a14ff189b30b3
push id33170
push usercbook@mozilla.com
push dateFri, 14 Oct 2016 10:37:07 +0000
treeherderautoland@0d101ebfd95c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs1277973
milestone52.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 1277973 - Baldr: prepare CallSiteAndTarget for another Kind (r=bbouvier) MozReview-Commit-ID: EJe83vhdKvT
js/src/asmjs/WasmBaselineCompile.cpp
js/src/asmjs/WasmFrameIterator.cpp
js/src/asmjs/WasmGenerator.cpp
js/src/asmjs/WasmIonCompile.cpp
js/src/asmjs/WasmStubs.cpp
js/src/asmjs/WasmTypes.h
js/src/jit/shared/Assembler-shared.h
--- a/js/src/asmjs/WasmBaselineCompile.cpp
+++ b/js/src/asmjs/WasmBaselineCompile.cpp
@@ -2191,22 +2191,22 @@ class BaseCompiler
           }
           default:
             MOZ_CRASH("Function argument type");
         }
     }
 
     void callDefinition(uint32_t funcDefIndex, const FunctionCall& call)
     {
-        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Relative);
+        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::FuncDef);
         masm.call(desc, funcDefIndex);
     }
 
     void callSymbolic(wasm::SymbolicAddress callee, const FunctionCall& call) {
-        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Register);
+        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Symbolic);
         masm.call(callee);
     }
 
     // Precondition: sync()
 
     void callIndirect(uint32_t sigIndex, Stk& indexVal, const FunctionCall& call)
     {
         loadI32(WasmTableCallIndexReg, indexVal);
@@ -2225,49 +2225,49 @@ class BaseCompiler
         } else {
             MOZ_ASSERT(sig.id.kind() != SigIdDesc::Kind::None);
             MOZ_ASSERT(mg_.tables.length() == 1);
             const TableDesc& table = mg_.tables[0];
 
             callee = CalleeDesc::wasmTable(table, sig.id);
         }
 
-        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Register);
+        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Dynamic);
         masm.wasmCallIndirect(desc, callee);
 
         // After return, restore the caller's TLS and pinned registers.
         loadFromFramePtr(WasmTlsReg, frameOffsetFromSlot(tlsSlot_, MIRType::Pointer));
         masm.loadWasmPinnedRegsFromTls();
     }
 
     // Precondition: sync()
 
     void callImport(unsigned globalDataOffset, const FunctionCall& call)
     {
         // There is no need to preserve WasmTlsReg since it has already been
         // spilt to a local slot.
 
-        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Register);
+        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Dynamic);
         CalleeDesc callee = CalleeDesc::import(globalDataOffset);
         masm.wasmCallImport(desc, callee);
 
         // After return, restore the caller's TLS and pinned registers.
         loadFromFramePtr(WasmTlsReg, frameOffsetFromSlot(tlsSlot_, MIRType::Pointer));
         masm.loadWasmPinnedRegsFromTls();
     }
 
     void builtinCall(SymbolicAddress builtin, const FunctionCall& call)
     {
         callSymbolic(builtin, call);
     }
 
     void builtinInstanceMethodCall(SymbolicAddress builtin, const ABIArg& instanceArg,
                                    const FunctionCall& call)
     {
-        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Register);
+        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Symbolic);
         masm.wasmCallBuiltinInstanceMethod(instanceArg, builtin);
     }
 
     //////////////////////////////////////////////////////////////////////
     //
     // Sundry low-level code generators.
 
     void addInterruptCheck()
--- a/js/src/asmjs/WasmFrameIterator.cpp
+++ b/js/src/asmjs/WasmFrameIterator.cpp
@@ -791,17 +791,17 @@ ProfilingFrameIterator::label() const
 }
 
 /*****************************************************************************/
 // Runtime patching to enable/disable profiling
 
 void
 wasm::ToggleProfiling(const Code& code, const CallSite& callSite, bool enabled)
 {
-    if (callSite.kind() != CallSite::Relative)
+    if (callSite.kind() != CallSite::FuncDef)
         return;
 
     uint8_t* callerRetAddr = code.segment().base() + callSite.returnAddressOffset();
 
 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
     void* callee = X86Encoding::GetRel32Target(callerRetAddr);
 #elif defined(JS_CODEGEN_ARM)
     uint8_t* caller = callerRetAddr - 4;
--- a/js/src/asmjs/WasmGenerator.cpp
+++ b/js/src/asmjs/WasmGenerator.cpp
@@ -271,50 +271,55 @@ ModuleGenerator::convertOutOfRangeBranch
     // create one thunk for each callee since there is often high reuse.
 
     OffsetMap alreadyThunked;
     if (!alreadyThunked.init())
         return false;
 
     for (; lastPatchedCallsite_ < masm_.callSites().length(); lastPatchedCallsite_++) {
         const CallSiteAndTarget& cs = masm_.callSites()[lastPatchedCallsite_];
-        if (!cs.isDefinition())
-            continue;
-
         uint32_t callerOffset = cs.returnAddressOffset();
         MOZ_RELEASE_ASSERT(callerOffset < INT32_MAX);
 
-        if (funcIsDefined(cs.funcDefIndex())) {
-            uint32_t calleeOffset = funcDefCodeRange(cs.funcDefIndex()).funcNonProfilingEntry();
-            MOZ_RELEASE_ASSERT(calleeOffset < INT32_MAX);
+        switch (cs.kind()) {
+          case CallSiteDesc::Dynamic:
+          case CallSiteDesc::Symbolic:
+            break;
+          case CallSiteDesc::FuncDef: {
+            if (funcIsDefined(cs.funcDefIndex())) {
+                uint32_t calleeOffset = funcDefCodeRange(cs.funcDefIndex()).funcNonProfilingEntry();
+                MOZ_RELEASE_ASSERT(calleeOffset < INT32_MAX);
 
-            if (uint32_t(abs(int32_t(calleeOffset) - int32_t(callerOffset))) < JumpRange()) {
-                masm_.patchCall(callerOffset, calleeOffset);
-                continue;
+                if (uint32_t(abs(int32_t(calleeOffset) - int32_t(callerOffset))) < JumpRange()) {
+                    masm_.patchCall(callerOffset, calleeOffset);
+                    break;
+                }
             }
-        }
 
-        OffsetMap::AddPtr p = alreadyThunked.lookupForAdd(cs.funcDefIndex());
-        if (!p) {
-            Offsets offsets;
-            offsets.begin = masm_.currentOffset();
-            uint32_t thunkOffset = masm_.thunkWithPatch().offset();
-            if (masm_.oom())
-                return false;
-            offsets.end = masm_.currentOffset();
+            OffsetMap::AddPtr p = alreadyThunked.lookupForAdd(cs.funcDefIndex());
+            if (!p) {
+                Offsets offsets;
+                offsets.begin = masm_.currentOffset();
+                uint32_t thunkOffset = masm_.thunkWithPatch().offset();
+                offsets.end = masm_.currentOffset();
+                if (masm_.oom())
+                    return false;
 
-            if (!metadata_->codeRanges.emplaceBack(CodeRange::CallThunk, offsets))
-                return false;
-            if (!metadata_->callThunks.emplaceBack(thunkOffset, cs.funcDefIndex()))
-                return false;
-            if (!alreadyThunked.add(p, cs.funcDefIndex(), offsets.begin))
-                return false;
+                if (!metadata_->codeRanges.emplaceBack(CodeRange::CallThunk, offsets))
+                    return false;
+                if (!metadata_->callThunks.emplaceBack(thunkOffset, cs.funcDefIndex()))
+                    return false;
+                if (!alreadyThunked.add(p, cs.funcDefIndex(), offsets.begin))
+                    return false;
+            }
+
+            masm_.patchCall(callerOffset, p->value());
+            break;
+          }
         }
-
-        masm_.patchCall(callerOffset, p->value());
     }
 
     // Create thunks for jumps to stubs. Stubs are always generated at the end
     // so unconditionally thunk all existing jump sites.
 
     for (JumpTarget target : MakeEnumeratedRange(JumpTarget::Limit)) {
         if (masm_.jumpSites()[target].empty())
             continue;
--- a/js/src/asmjs/WasmIonCompile.cpp
+++ b/js/src/asmjs/WasmIonCompile.cpp
@@ -978,17 +978,17 @@ class FunctionCompiler
     bool callDefinition(const Sig& sig, uint32_t funcDefIndex, const CallCompileState& call,
                         MDefinition** def)
     {
         if (inDeadCode()) {
             *def = nullptr;
             return true;
         }
 
-        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Relative);
+        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::FuncDef);
         MIRType ret = ToMIRType(sig.ret());
         auto callee = CalleeDesc::definition(funcDefIndex);
         auto* ins = MWasmCall::New(alloc(), desc, callee, call.regArgs_, ret,
                                    call.spIncrement_, MWasmCall::DontSaveTls);
         if (!ins)
             return false;
 
         curBlock_->add(ins);
@@ -1025,17 +1025,17 @@ class FunctionCompiler
             MOZ_ASSERT(sig.id.kind() != SigIdDesc::Kind::None);
             MOZ_ASSERT(mg_.tables.length() == 1);
             const TableDesc& table = mg_.tables[0];
             MOZ_ASSERT(table.external == (call.tlsStackOffset_ != MWasmCall::DontSaveTls));
 
             callee = CalleeDesc::wasmTable(table, sig.id);
         }
 
-        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Register);
+        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Dynamic);
         auto* ins = MWasmCall::New(alloc(), desc, callee, call.regArgs_, ToMIRType(sig.ret()),
                                    call.spIncrement_, call.tlsStackOffset_, index);
         if (!ins)
             return false;
 
         curBlock_->add(ins);
         *def = ins;
         return true;
@@ -1046,17 +1046,17 @@ class FunctionCompiler
     {
         if (inDeadCode()) {
             *def = nullptr;
             return true;
         }
 
         MOZ_ASSERT(call.tlsStackOffset_ != MWasmCall::DontSaveTls);
 
-        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Register);
+        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Dynamic);
         auto callee = CalleeDesc::import(globalDataOffset);
         auto* ins = MWasmCall::New(alloc(), desc, callee, call.regArgs_, ToMIRType(ret),
                                    call.spIncrement_, call.tlsStackOffset_);
         if (!ins)
             return false;
 
         curBlock_->add(ins);
         *def = ins;
@@ -1066,17 +1066,17 @@ class FunctionCompiler
     bool builtinCall(SymbolicAddress builtin, const CallCompileState& call, ValType ret,
                      MDefinition** def)
     {
         if (inDeadCode()) {
             *def = nullptr;
             return true;
         }
 
-        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Register);
+        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Symbolic);
         auto callee = CalleeDesc::builtin(builtin);
         auto* ins = MWasmCall::New(alloc(), desc, callee, call.regArgs_, ToMIRType(ret),
                                    call.spIncrement_, MWasmCall::DontSaveTls);
         if (!ins)
             return false;
 
         curBlock_->add(ins);
         *def = ins;
@@ -1086,17 +1086,17 @@ class FunctionCompiler
     bool builtinInstanceMethodCall(SymbolicAddress builtin, const CallCompileState& call,
                                    ValType ret, MDefinition** def)
     {
         if (inDeadCode()) {
             *def = nullptr;
             return true;
         }
 
-        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Register);
+        CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Symbolic);
         auto* ins = MWasmCall::NewBuiltinInstanceMethodCall(alloc(), desc, builtin,
                                                             call.instanceArg_, call.regArgs_,
                                                             ToMIRType(ret), call.spIncrement_,
                                                             call.tlsStackOffset_);
         if (!ins)
             return false;
 
         curBlock_->add(ins);
--- a/js/src/asmjs/WasmStubs.cpp
+++ b/js/src/asmjs/WasmStubs.cpp
@@ -259,17 +259,17 @@ wasm::GenerateEntry(MacroAssembler& masm
                 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("unexpected stack arg type");
             }
             break;
         }
     }
 
     // Call into the real function.
     masm.assertStackAlignment(AsmJSStackAlignment);
-    masm.call(CallSiteDesc(CallSiteDesc::Relative), func.funcDefIndex());
+    masm.call(CallSiteDesc(CallSiteDesc::FuncDef), func.funcDefIndex());
 
     // Recover the stack pointer value before dynamic alignment.
     masm.loadWasmActivationFromTls(scratch);
     masm.loadStackPtr(Address(scratch, WasmActivation::offsetOfEntrySP()));
     masm.setFramePushed(FramePushedForEntrySP);
 
     // Recover the 'argv' pointer which was saved before aligning the stack.
     masm.Pop(argv);
--- a/js/src/asmjs/WasmTypes.h
+++ b/js/src/asmjs/WasmTypes.h
@@ -711,31 +711,35 @@ struct FuncOffsets : ProfilingOffsets
 // While the frame-pointer chain allows the stack to be unwound without
 // metadata, Error.stack still needs to know the line/column of every call in
 // the chain. A CallSiteDesc describes a single callsite to which CallSite adds
 // the metadata necessary to walk up to the next frame. Lastly CallSiteAndTarget
 // adds the function index of the callee.
 
 class CallSiteDesc
 {
-    uint32_t lineOrBytecode_ : 31;
-    uint32_t kind_ : 1;
+    uint32_t lineOrBytecode_ : 30;
+    uint32_t kind_ : 2;
   public:
     enum Kind {
-        Relative,  // pc-relative call
-        Register   // call *register
+        FuncDef,   // pc-relative call to a specific function
+        Dynamic,   // dynamic callee called via register
+        Symbolic   // call to a single symbolic callee
     };
     CallSiteDesc() {}
     explicit CallSiteDesc(Kind kind)
       : lineOrBytecode_(0), kind_(kind)
-    {}
+    {
+        MOZ_ASSERT(kind == Kind(kind_));
+    }
     CallSiteDesc(uint32_t lineOrBytecode, Kind kind)
       : lineOrBytecode_(lineOrBytecode), kind_(kind)
     {
-        MOZ_ASSERT(lineOrBytecode_ == lineOrBytecode, "must fit in 31 bits");
+        MOZ_ASSERT(kind == Kind(kind_));
+        MOZ_ASSERT(lineOrBytecode == lineOrBytecode_);
     }
     uint32_t lineOrBytecode() const { return lineOrBytecode_; }
     Kind kind() const { return Kind(kind_); }
 };
 
 class CallSite : public CallSiteDesc
 {
     uint32_t returnAddressOffset_;
@@ -763,24 +767,28 @@ class CallSite : public CallSiteDesc
 
 WASM_DECLARE_POD_VECTOR(CallSite, CallSiteVector)
 
 class CallSiteAndTarget : public CallSite
 {
     uint32_t funcDefIndex_;
 
   public:
+    explicit CallSiteAndTarget(CallSite cs)
+      : CallSite(cs)
+    {
+        MOZ_ASSERT(cs.kind() != FuncDef);
+    }
     CallSiteAndTarget(CallSite cs, uint32_t funcDefIndex)
       : CallSite(cs), funcDefIndex_(funcDefIndex)
-    { }
+    {
+        MOZ_ASSERT(cs.kind() == FuncDef);
+    }
 
-    static const uint32_t NOT_DEFINITION = UINT32_MAX;
-
-    bool isDefinition() const { return funcDefIndex_ != NOT_DEFINITION; }
-    uint32_t funcDefIndex() const { MOZ_ASSERT(isDefinition()); return funcDefIndex_; }
+    uint32_t funcDefIndex() const { MOZ_ASSERT(kind() == FuncDef); return funcDefIndex_; }
 };
 
 typedef Vector<CallSiteAndTarget, 0, SystemAllocPolicy> CallSiteAndTargetVector;
 
 // A wasm::SymbolicAddress represents a pointer to a well-known function or
 // object that is embedded in wasm code. Since wasm code is serialized and
 // later deserialized into a different address space, symbolic addresses must be
 // used for *all* pointers into the address space. The MacroAssembler records a
--- a/js/src/jit/shared/Assembler-shared.h
+++ b/js/src/jit/shared/Assembler-shared.h
@@ -748,23 +748,24 @@ class AssemblerShared
     bool oom() const {
         return !enoughMemory_;
     }
 
     bool embedsNurseryPointers() const {
         return embedsNurseryPointers_;
     }
 
+    template <typename... Args>
     void append(const wasm::CallSiteDesc& desc, CodeOffset retAddr, size_t framePushed,
-                uint32_t funcDefIndex = wasm::CallSiteAndTarget::NOT_DEFINITION)
+                Args&&... args)
     {
-        // framePushed does not include sizeof(AsmJSFrame), so add it in here (see
-        // CallSite::stackDepth).
-        wasm::CallSite callsite(desc, retAddr.offset(), framePushed + sizeof(AsmJSFrame));
-        enoughMemory_ &= callsites_.append(wasm::CallSiteAndTarget(callsite, funcDefIndex));
+        // framePushed does not include sizeof(AsmJSFrame), so add it in explicitly when
+        // setting the CallSite::stackDepth.
+        wasm::CallSite cs(desc, retAddr.offset(), framePushed + sizeof(AsmJSFrame));
+        enoughMemory_ &= callsites_.emplaceBack(cs, mozilla::Forward<Args>(args)...);
     }
     wasm::CallSiteAndTargetVector& callSites() { return callsites_; }
 
     void append(wasm::JumpTarget target, uint32_t offset) {
         enoughMemory_ &= jumpsites_[target].append(offset);
     }
     const wasm::JumpSiteArray& jumpSites() { return jumpsites_; }
     void clearJumpSites() { for (auto& v : jumpsites_) v.clear(); }