author | Luke Wagner <luke@mozilla.com> |
Thu, 13 Oct 2016 13:17:55 -0500 | |
changeset 317901 | e29daffaaca4b5a22756d631eac82d920a701c62 |
parent 317900 | e6d2b67b35e5d0d48949b05c9599b892cf70ba68 |
child 317902 | 33b295d58244ce40eda37a5ce57a14ff189b30b3 |
push id | 33170 |
push user | cbook@mozilla.com |
push date | Fri, 14 Oct 2016 10:37:07 +0000 |
treeherder | autoland@0d101ebfd95c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bbouvier |
bugs | 1277973 |
milestone | 52.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
|
--- 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(); }