diff --git a/accessible/ipc/ProxyAccessible.h b/accessible/ipc/ProxyAccessible.h index 882c925969..0b6af4d0f5 100644 --- a/accessible/ipc/ProxyAccessible.h +++ b/accessible/ipc/ProxyAccessible.h @@ -306,7 +306,7 @@ public: protected: explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc) : mParent(nullptr), mDoc(aThisAsDoc), mWrapper(0), mID(0), - mRole(roles::DOCUMENT) + mRole(roles::DOCUMENT), mOuterDoc(false) { MOZ_COUNT_CTOR(ProxyAccessible); } protected: diff --git a/dom/bindings/OwningNonNull.h b/dom/bindings/OwningNonNull.h index c0b01446f7..aaceb2c23b 100644 --- a/dom/bindings/OwningNonNull.h +++ b/dom/bindings/OwningNonNull.h @@ -147,7 +147,7 @@ nsCOMPtr::operator=(const mozilla::dom::OwningNonNull& aOther) return operator=(aOther.get()); } -// Declared in nsRefPtr.h +// Declared in mozilla/nsRefPtr.h template template nsRefPtr::nsRefPtr(const mozilla::dom::OwningNonNull& aOther) : nsRefPtr(aOther.get()) diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 6e3542ead0..8743972a63 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -5105,6 +5105,17 @@ ContentParent::RecvEndDriverCrashGuard(const uint32_t& aGuardType) return true; } +bool +ContentParent::RecvGetDeviceStorageLocation(const nsString& aType, + nsString* aPath) { +#ifdef MOZ_WIDGET_ANDROID + mozilla::AndroidBridge::GetExternalPublicDirectory(aType, *aPath); + return true; +#else + return false; +#endif +} + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index dd5ad970b2..585ce1ed06 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -855,6 +855,8 @@ private: virtual bool RecvProfile(const nsCString& aProfile) override; virtual bool RecvGetGraphicsDeviceInitData(DeviceInitData* aOut) override; + virtual bool RecvGetDeviceStorageLocation(const nsString& aType, + nsString* aPath) override; // If you add strong pointers to cycle collected objects here, be sure to // release these objects in ShutDownProcess. See the comment there for more // details. diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 8379ff57bc..ccbee2c260 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -1068,6 +1068,9 @@ parent: sync GetGraphicsDeviceInitData() returns (DeviceInitData aData); + sync GetDeviceStorageLocation(nsString type) + returns (nsString path); + both: AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, Principal aPrincipal); diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp index 0765072859..44082ed0a1 100644 --- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -403,7 +403,9 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar, if (!CallNPN_GetValue_NPNVdocumentOrigin(&v, &result)) { return NPERR_GENERIC_ERROR; } - if (result == NPERR_NO_ERROR) { + if (result == NPERR_NO_ERROR || + (GetQuirks() & + PluginModuleChild::QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN)) { *static_cast(aValue) = ToNewCString(v); } return result; diff --git a/dom/plugins/ipc/PluginModuleChild.cpp b/dom/plugins/ipc/PluginModuleChild.cpp index abcbd857fa..85f99ea81d 100644 --- a/dom/plugins/ipc/PluginModuleChild.cpp +++ b/dom/plugins/ipc/PluginModuleChild.cpp @@ -149,7 +149,7 @@ PluginModuleChild::PluginModuleChild(bool aIsChrome) MOZ_ASSERT(!gChromeInstance); gChromeInstance = this; } - mUserAgent.SetIsVoid(true); + #ifdef XP_MACOSX if (aIsChrome) { mac_plugin_interposing::child::SetUpCocoaInterposing(); @@ -2095,15 +2095,18 @@ PluginModuleChild::InitQuirksModes(const nsCString& aMimeType) #endif } -#ifdef OS_WIN if (specialType == nsPluginHost::eSpecialType_Flash) { + mQuirks |= QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN; +#ifdef OS_WIN mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK; mQuirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS; mQuirks |= QUIRK_FLASH_HOOK_SETLONGPTR; mQuirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO; mQuirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE; +#endif } +#ifdef OS_WIN // QuickTime plugin usually loaded with audio/mpeg mimetype NS_NAMED_LITERAL_CSTRING(quicktime, "npqtplugin"); if (FindInReadable(quicktime, mPluginFilename)) { diff --git a/dom/plugins/ipc/PluginModuleChild.h b/dom/plugins/ipc/PluginModuleChild.h index 06cf7205f7..d526d6450d 100644 --- a/dom/plugins/ipc/PluginModuleChild.h +++ b/dom/plugins/ipc/PluginModuleChild.h @@ -266,8 +266,12 @@ public: // CGContextRef we pass to it in NPP_HandleEvent(NPCocoaEventDrawRect) // outside of that call. See bug 804606. QUIRK_FLASH_AVOID_CGMODE_CRASHES = 1 << 10, + // Work around a Flash bug where it fails to check the error code of a + // NPN_GetValue(NPNVdocumentOrigin) call before trying to dereference + // its char* output. + QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN = 1 << 11, // Win: Addresses a Unity bug with mouse capture. - QUIRK_UNITY_FIXUP_MOUSE_CAPTURE = 1 << 11, + QUIRK_UNITY_FIXUP_MOUSE_CAPTURE = 1 << 12, }; int GetQuirks() { return mQuirks; } @@ -303,7 +307,6 @@ private: PRLibrary* mLibrary; nsCString mPluginFilename; // UTF8 - nsCString mUserAgent; int mQuirks; bool mIsChrome; diff --git a/editor/libeditor/nsEditor.cpp b/editor/libeditor/nsEditor.cpp index af01c4326a..74ae95d945 100644 --- a/editor/libeditor/nsEditor.cpp +++ b/editor/libeditor/nsEditor.cpp @@ -3802,6 +3802,33 @@ nsEditor::IsPreformatted(nsIDOMNode *aNode, bool *aResult) // a new element, for instance, if that's why you were splitting // the node. // +int32_t +nsEditor::SplitNodeDeep(nsIContent& aNode, nsIContent& aSplitPointParent, + int32_t aSplitPointOffset, + EmptyContainers aEmptyContainers, + nsIContent** outLeftNode, + nsIContent** outRightNode) +{ + int32_t offset; + nsCOMPtr leftNodeDOM, rightNodeDOM; + nsresult res = SplitNodeDeep(aNode.AsDOMNode(), + aSplitPointParent.AsDOMNode(), aSplitPointOffset, &offset, + aEmptyContainers == EmptyContainers::no, address_of(leftNodeDOM), + address_of(rightNodeDOM)); + NS_ENSURE_SUCCESS(res, -1); + if (outLeftNode) { + nsCOMPtr leftNode = do_QueryInterface(leftNodeDOM); + MOZ_ASSERT(!leftNodeDOM || leftNode); + leftNode.forget(outLeftNode); + } + if (outRightNode) { + nsCOMPtr rightNode = do_QueryInterface(rightNodeDOM); + MOZ_ASSERT(!rightNodeDOM || rightNode); + rightNode.forget(outRightNode); + } + return offset; +} + nsresult nsEditor::SplitNodeDeep(nsIDOMNode *aNode, nsIDOMNode *aSplitPointParent, diff --git a/editor/libeditor/nsEditor.h b/editor/libeditor/nsEditor.h index 24dbfe29e4..780900ce34 100644 --- a/editor/libeditor/nsEditor.h +++ b/editor/libeditor/nsEditor.h @@ -638,13 +638,17 @@ public: nsresult IsPreformatted(nsIDOMNode *aNode, bool *aResult); - nsresult SplitNodeDeep(nsIDOMNode *aNode, - nsIDOMNode *aSplitPointParent, - int32_t aSplitPointOffset, - int32_t *outOffset, - bool aNoEmptyContainers = false, - nsCOMPtr *outLeftNode = 0, - nsCOMPtr *outRightNode = 0); + enum class EmptyContainers { no, yes }; + int32_t SplitNodeDeep(nsIContent& aNode, nsIContent& aSplitPointParent, + int32_t aSplitPointOffset, + EmptyContainers aEmptyContainers = + EmptyContainers::yes, + nsIContent** outLeftNode = nullptr, + nsIContent** outRightNode = nullptr); + nsresult SplitNodeDeep(nsIDOMNode* aNode, nsIDOMNode* aSplitPointParent, + int32_t aSplitPointOffset, int32_t* outOffset, bool aNoEmptyContainers = + false, nsCOMPtr* outLeftNode = nullptr, nsCOMPtr* + outRightNode = nullptr); ::DOMPoint JoinNodeDeep(nsIContent& aLeftNode, nsIContent& aRightNode); nsresult GetString(const nsAString& name, nsAString& value); diff --git a/js/src/jit-test/tests/ion/bug1181354.js b/js/src/jit-test/tests/ion/bug1181354.js new file mode 100644 index 0000000000..bef39feed6 --- /dev/null +++ b/js/src/jit-test/tests/ion/bug1181354.js @@ -0,0 +1,9 @@ +for (a of []) {} +var log = ""; +(function() { + for (a of [,0]) {} + const y = "FOO"; + log += y; + function inner() { log += y; } +})() +assertEq(log, "FOO"); diff --git a/js/src/jit-test/tests/ion/scalar-replacement-bug1138693.js b/js/src/jit-test/tests/ion/scalar-replacement-bug1138693.js new file mode 100644 index 0000000000..4f98c0d338 --- /dev/null +++ b/js/src/jit-test/tests/ion/scalar-replacement-bug1138693.js @@ -0,0 +1,22 @@ +if (!this.hasOwnProperty("TypedObject")) + quit(); + +var T = TypedObject; +var ST = new T.StructType({x:T.int32}); +function check(v) { + return v.toSource(); +} +function test() { + var fake = { toSource: ST.toSource }; + try { + check(fake); + } catch (e) {} +} +test(); +var uint8 = TypedObject.uint8; +function runTests() { + uint8.toSource(); +} +runTests(); +test(); + diff --git a/js/src/jit/Bailouts.h b/js/src/jit/Bailouts.h index 624c9cfa8d..7966015efb 100644 --- a/js/src/jit/Bailouts.h +++ b/js/src/jit/Bailouts.h @@ -137,8 +137,8 @@ class BailoutFrameInfo SnapshotOffset snapshotOffset() const { return snapshotOffset_; } - const MachineState machineState() const { - return machine_; + const MachineState* machineState() const { + return &machine_; } size_t topFrameSize() const { return topFrameSize_; diff --git a/js/src/jit/BaselineBailouts.cpp b/js/src/jit/BaselineBailouts.cpp index bf3d8ba2c4..60a0e69774 100644 --- a/js/src/jit/BaselineBailouts.cpp +++ b/js/src/jit/BaselineBailouts.cpp @@ -412,7 +412,7 @@ class SnapshotIteratorForBailout : public SnapshotIterator public: SnapshotIteratorForBailout(JitActivation* activation, JitFrameIterator& iter) - : SnapshotIterator(iter), + : SnapshotIterator(iter, activation->bailoutData()->machineState()), activation_(activation), iter_(iter) { diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index dc89921100..59b8f2ba42 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -3340,6 +3340,34 @@ BaselineCompiler::emit_JSOP_TOID() return true; } +typedef JSString* (*ToStringFn)(JSContext*, HandleValue); +static const VMFunction ToStringInfo = FunctionInfo(ToStringSlow); + +bool +BaselineCompiler::emit_JSOP_TOSTRING() +{ + // Keep top stack value in R0. + frame.popRegsAndSync(1); + + // Inline path for string. + Label done; + masm.branchTestString(Assembler::Equal, R0, &done); + + prepareVMCall(); + + pushArg(R0); + + // Call ToStringSlow which doesn't handle string inputs. + if (!callVM(ToStringInfo)) + return false; + + masm.tagValue(JSVAL_TYPE_STRING, ReturnReg, R0); + + masm.bind(&done); + frame.push(R0); + return true; +} + bool BaselineCompiler::emit_JSOP_TABLESWITCH() { diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h index e0d54e33b9..f082ee9e81 100644 --- a/js/src/jit/BaselineCompiler.h +++ b/js/src/jit/BaselineCompiler.h @@ -184,6 +184,7 @@ namespace jit { _(JSOP_RUNONCE) \ _(JSOP_REST) \ _(JSOP_TOID) \ + _(JSOP_TOSTRING) \ _(JSOP_TABLESWITCH) \ _(JSOP_ITER) \ _(JSOP_MOREITER) \ diff --git a/js/src/jit/JitFrameIterator.h b/js/src/jit/JitFrameIterator.h index 5a30f118ca..a536c22d0a 100644 --- a/js/src/jit/JitFrameIterator.h +++ b/js/src/jit/JitFrameIterator.h @@ -410,7 +410,7 @@ class SnapshotIterator SnapshotReader snapshot_; RecoverReader recover_; JitFrameLayout* fp_; - MachineState machine_; + const MachineState* machine_; IonScript* ionScript_; RInstructionResults* instructionResults_; @@ -429,17 +429,17 @@ class SnapshotIterator private: // Read a spilled register from the machine state. bool hasRegister(Register reg) const { - return machine_.has(reg); + return machine_->has(reg); } uintptr_t fromRegister(Register reg) const { - return machine_.read(reg); + return machine_->read(reg); } bool hasRegister(FloatRegister reg) const { - return machine_.has(reg); + return machine_->has(reg); } double fromRegister(FloatRegister reg) const { - return machine_.read(reg); + return machine_->read(reg); } // Read an uintptr_t from the stack. @@ -550,9 +550,7 @@ class SnapshotIterator // Connect all informations about the current script in order to recover the // content of baseline frames. - SnapshotIterator(IonScript* ionScript, SnapshotOffset snapshotOffset, - JitFrameLayout* fp, const MachineState& machine); - explicit SnapshotIterator(const JitFrameIterator& iter); + SnapshotIterator(const JitFrameIterator& iter, const MachineState* machineState); SnapshotIterator(); Value read() { @@ -657,6 +655,9 @@ class InlineFrameIterator jsbytecode* pc_; uint32_t numActualArgs_; + // Register state, used by all snapshot iterators. + MachineState machine_; + struct Nop { void operator()(const Value& v) { } }; diff --git a/js/src/jit/JitFrames.cpp b/js/src/jit/JitFrames.cpp index bdf31ca6e6..c26f416e37 100644 --- a/js/src/jit/JitFrames.cpp +++ b/js/src/jit/JitFrames.cpp @@ -353,12 +353,12 @@ JitFrameIterator::machineState() const // The MachineState is used by GCs for marking call-sites. if (MOZ_UNLIKELY(isBailoutJS())) - return activation_->bailoutData()->machineState(); + return *activation_->bailoutData()->machineState(); SafepointReader reader(ionScript(), safepoint()); uintptr_t* spill = spillBase(); - MachineState machine; + for (GeneralRegisterBackwardIterator iter(reader.allGprSpills()); iter.more(); iter++) machine.setRegisterLocation(*iter, --spill); @@ -1163,7 +1163,7 @@ MarkBailoutFrame(JSTracer* trc, const JitFrameIterator& frame) // The vector of recover instructions is already traced as part of the // JitActivation. - SnapshotIterator snapIter(frame); + SnapshotIterator snapIter(frame, frame.activation()->bailoutData()->machineState()); // For each instruction, we read the allocations without evaluating the // recover instruction, nor reconstructing the frame. We are only looking at @@ -1754,24 +1754,7 @@ RInstructionResults::trace(JSTracer* trc) } -SnapshotIterator::SnapshotIterator(IonScript* ionScript, SnapshotOffset snapshotOffset, - JitFrameLayout* fp, const MachineState& machine) - : snapshot_(ionScript->snapshots(), - snapshotOffset, - ionScript->snapshotsRVATableSize(), - ionScript->snapshotsListSize()), - recover_(snapshot_, - ionScript->recovers(), - ionScript->recoversSize()), - fp_(fp), - machine_(machine), - ionScript_(ionScript), - instructionResults_(nullptr) -{ - MOZ_ASSERT(snapshotOffset < ionScript->snapshotsListSize()); -} - -SnapshotIterator::SnapshotIterator(const JitFrameIterator& iter) +SnapshotIterator::SnapshotIterator(const JitFrameIterator& iter, const MachineState* machineState) : snapshot_(iter.ionScript()->snapshots(), iter.snapshotOffset(), iter.ionScript()->snapshotsRVATableSize(), @@ -1780,7 +1763,7 @@ SnapshotIterator::SnapshotIterator(const JitFrameIterator& iter) iter.ionScript()->recovers(), iter.ionScript()->recoversSize()), fp_(iter.jsFrame()), - machine_(iter.machineState()), + machine_(machineState), ionScript_(iter.ionScript()), instructionResults_(nullptr) { @@ -2012,7 +1995,7 @@ SnapshotIterator::floatAllocationPointer(const RValueAllocation& alloc) const { switch (alloc.mode()) { case RValueAllocation::ANY_FLOAT_REG: - return machine_.address(alloc.fpuReg()); + return machine_->address(alloc.fpuReg()); case RValueAllocation::ANY_FLOAT_STACK: return (FloatRegisters::RegisterContent*) AddressOfFrameSlot(fp_, alloc.stackOffset()); @@ -2065,7 +2048,7 @@ SnapshotIterator::writeAllocationValuePayload(const RValueAllocation& alloc, Val break; case RValueAllocation::TYPED_REG: - machine_.write(alloc.reg2(), payload); + machine_->write(alloc.reg2(), payload); break; case RValueAllocation::TYPED_STACK: @@ -2084,7 +2067,7 @@ SnapshotIterator::writeAllocationValuePayload(const RValueAllocation& alloc, Val #if defined(JS_NUNBOX32) case RValueAllocation::UNTYPED_REG_REG: case RValueAllocation::UNTYPED_STACK_REG: - machine_.write(alloc.reg2(), payload); + machine_->write(alloc.reg2(), payload); break; case RValueAllocation::UNTYPED_REG_STACK: @@ -2093,7 +2076,7 @@ SnapshotIterator::writeAllocationValuePayload(const RValueAllocation& alloc, Val break; #elif defined(JS_PUNBOX64) case RValueAllocation::UNTYPED_REG: - machine_.write(alloc.reg(), v.asRawBits()); + machine_->write(alloc.reg(), v.asRawBits()); break; case RValueAllocation::UNTYPED_STACK: @@ -2203,7 +2186,8 @@ SnapshotIterator::initInstructionResults(MaybeReadFallback& fallback) // Start a new snapshot at the beginning of the JitFrameIterator. This // SnapshotIterator is used for evaluating the content of all recover // instructions. The result is then saved on the JitActivation. - SnapshotIterator s(*fallback.frame); + MachineState machine = fallback.frame->machineState(); + SnapshotIterator s(*fallback.frame, &machine); if (!s.computeInstructionResults(cx, results)) { // If the evaluation failed because of OOMs, then we discard the @@ -2395,7 +2379,8 @@ InlineFrameIterator::InlineFrameIterator(JSContext* cx, const InlineFrameIterato script_(cx) { if (frame_) { - start_ = SnapshotIterator(*frame_); + machine_ = iter->machine_; + start_ = SnapshotIterator(*frame_, &machine_); // findNextFrame will iterate to the next frame and init. everything. // Therefore to settle on the same frame, we report one frame less readed. @@ -2412,7 +2397,8 @@ InlineFrameIterator::resetOn(const JitFrameIterator* iter) frameCount_ = UINT32_MAX; if (iter) { - start_ = SnapshotIterator(*iter); + machine_ = iter->machineState(); + start_ = SnapshotIterator(*iter, &machine_); findNextFrame(); } } diff --git a/js/src/jit/Registers.h b/js/src/jit/Registers.h index d2dd6ef58c..3644329de7 100644 --- a/js/src/jit/Registers.h +++ b/js/src/jit/Registers.h @@ -112,7 +112,10 @@ class RegisterDump } }; -// Information needed to recover machine register state. +// Information needed to recover machine register state. This records the +// location of spilled register and not the content of the spilled +// registers. Thus we can safely assume that this structure is unchanged, even +// if the GC pointers mapped by this structure are relocated. class MachineState { mozilla::Array regs_; @@ -120,10 +123,12 @@ class MachineState public: MachineState() { +#ifndef JS_CODEGEN_NONE for (unsigned i = 0; i < Registers::Total; i++) regs_[i] = reinterpret_cast(i + 0x100); for (unsigned i = 0; i < FloatRegisters::Total; i++) fpregs_[i] = reinterpret_cast(i + 0x200); +#endif } static MachineState FromBailout(RegisterDump::GPRArray& regs, RegisterDump::FPUArray& fpregs); diff --git a/js/src/jit/ScalarReplacement.cpp b/js/src/jit/ScalarReplacement.cpp index cc47d6e8e6..e1444caf69 100644 --- a/js/src/jit/ScalarReplacement.cpp +++ b/js/src/jit/ScalarReplacement.cpp @@ -224,7 +224,7 @@ IsObjectEscaped(MInstruction* ins, JSObject* objDefault) case MDefinition::Op_GuardShape: { MGuardShape* guard = def->toGuardShape(); MOZ_ASSERT(!ins->isGuardShape()); - if (obj->as().lastProperty() != guard->shape()) { + if (obj->maybeShape() != guard->shape()) { JitSpewDef(JitSpew_Escape, "has a non-matching guard shape\n", guard); return true; } @@ -511,6 +511,8 @@ ObjectMemoryView::visitStoreFixedSlot(MStoreFixedSlot* ins) state_->setFixedSlot(ins->slot(), ins->value()); ins->block()->insertBefore(ins->toInstruction(), state_); } else { + // UnsafeSetReserveSlot can access baked-in slots which are guarded by + // conditions, which are not seen by the escape analysis. MBail* bailout = MBail::New(alloc_, Bailout_Inevitable); ins->block()->insertBefore(ins, bailout); } @@ -530,6 +532,8 @@ ObjectMemoryView::visitLoadFixedSlot(MLoadFixedSlot* ins) if (state_->hasFixedSlot(ins->slot())) { ins->replaceAllUsesWith(state_->getFixedSlot(ins->slot())); } else { + // UnsafeGetReserveSlot can access baked-in slots which are guarded by + // conditions, which are not seen by the escape analysis. MBail* bailout = MBail::New(alloc_, Bailout_Inevitable); ins->block()->insertBefore(ins, bailout); ins->replaceAllUsesWith(undefinedVal_); @@ -572,6 +576,8 @@ ObjectMemoryView::visitStoreSlot(MStoreSlot* ins) state_->setDynamicSlot(ins->slot(), ins->value()); ins->block()->insertBefore(ins->toInstruction(), state_); } else { + // UnsafeSetReserveSlot can access baked-in slots which are guarded by + // conditions, which are not seen by the escape analysis. MBail* bailout = MBail::New(alloc_, Bailout_Inevitable); ins->block()->insertBefore(ins, bailout); } @@ -595,6 +601,8 @@ ObjectMemoryView::visitLoadSlot(MLoadSlot* ins) if (state_->hasDynamicSlot(ins->slot())) { ins->replaceAllUsesWith(state_->getDynamicSlot(ins->slot())); } else { + // UnsafeGetReserveSlot can access baked-in slots which are guarded by + // conditions, which are not seen by the escape analysis. MBail* bailout = MBail::New(alloc_, Bailout_Inevitable); ins->block()->insertBefore(ins, bailout); ins->replaceAllUsesWith(undefinedVal_); diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index 7d15c5ba65..672ff6b316 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -435,7 +435,7 @@ SetProperty(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValu JSOp op = JSOp(*pc); - if (op == JSOP_SETALIASEDVAR) { + if (op == JSOP_SETALIASEDVAR || op == JSOP_INITALIASEDLEXICAL) { // Aliased var assigns ignore readonly attributes on the property, as // required for initializing 'const' closure variables. Shape* shape = obj->as().lookup(cx, name); diff --git a/js/src/jit/arm/Lowering-arm.cpp b/js/src/jit/arm/Lowering-arm.cpp index 054cf28fd8..ab5244577f 100644 --- a/js/src/jit/arm/Lowering-arm.cpp +++ b/js/src/jit/arm/Lowering-arm.cpp @@ -659,10 +659,10 @@ LIRGeneratorARM::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins) if (byteSize(ins->accessType()) != 4 && !HasLDSTREXBHD()) { LAsmJSCompareExchangeCallout* lir = - new(alloc()) LAsmJSCompareExchangeCallout(useRegister(ptr), - useRegister(ins->oldValue()), - useRegister(ins->newValue())); - defineFixed(lir, ins, LAllocation(AnyRegister(ReturnReg))); + new(alloc()) LAsmJSCompareExchangeCallout(useRegisterAtStart(ptr), + useRegisterAtStart(ins->oldValue()), + useRegisterAtStart(ins->newValue())); + defineReturn(lir, ins); return; } @@ -680,14 +680,12 @@ LIRGeneratorARM::visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins) MOZ_ASSERT(ins->ptr()->type() == MIRType_Int32); MOZ_ASSERT(ins->accessType() < Scalar::Float32); - const LAllocation ptr = useRegister(ins->ptr()); - const LAllocation value = useRegister(ins->value()); + const LAllocation ptr = useRegisterAtStart(ins->ptr()); + const LAllocation value = useRegisterAtStart(ins->value()); if (byteSize(ins->accessType()) < 4 && !HasLDSTREXBHD()) { // Call out on ARMv6. - defineFixed(new(alloc()) LAsmJSAtomicExchangeCallout(ptr, value), - ins, - LAllocation(AnyRegister(ReturnReg))); + defineReturn(new(alloc()) LAsmJSAtomicExchangeCallout(ptr, value), ins); return; } @@ -704,8 +702,9 @@ LIRGeneratorARM::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins) if (byteSize(ins->accessType()) != 4 && !HasLDSTREXBHD()) { LAsmJSAtomicBinopCallout* lir = - new(alloc()) LAsmJSAtomicBinopCallout(useRegister(ptr), useRegister(ins->value())); - defineFixed(lir, ins, LAllocation(AnyRegister(ReturnReg))); + new(alloc()) LAsmJSAtomicBinopCallout(useRegisterAtStart(ptr), + useRegisterAtStart(ins->value())); + defineReturn(lir, ins); return; } diff --git a/js/src/jit/arm64/MacroAssembler-arm64.h b/js/src/jit/arm64/MacroAssembler-arm64.h index 2049ca02f2..a8558feee3 100644 --- a/js/src/jit/arm64/MacroAssembler-arm64.h +++ b/js/src/jit/arm64/MacroAssembler-arm64.h @@ -2870,6 +2870,10 @@ class MacroAssemblerCompat : public vixl::MacroAssembler // Emit a BLR or NOP instruction. ToggleCall can be used to patch // this instruction. CodeOffsetLabel toggledCall(JitCode* target, bool enabled) { + // The returned offset must be to the first instruction generated, + // for the debugger to match offset with Baseline's pcMappingEntries_. + BufferOffset offset = nextOffset(); + // TODO: Random pool insertion between instructions below is terrible. // Unfortunately, we can't forbid pool prevention, because we're trying // to add an entry to a pool. So as a temporary fix, just flush the pool @@ -2879,7 +2883,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler syncStackPtr(); - BufferOffset offset = nextOffset(); BufferOffset loadOffset; { vixl::UseScratchRegisterScope temps(this); diff --git a/js/src/jit/shared/CodeGenerator-shared.cpp b/js/src/jit/shared/CodeGenerator-shared.cpp index c854422976..ffcf9b182c 100644 --- a/js/src/jit/shared/CodeGenerator-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-shared.cpp @@ -1052,7 +1052,7 @@ CodeGeneratorShared::markSafepoint(LInstruction* ins) void CodeGeneratorShared::markSafepointAt(uint32_t offset, LInstruction* ins) { - MOZ_ASSERT_IF(!safepointIndices_.empty(), + MOZ_ASSERT_IF(!safepointIndices_.empty() && !masm.oom(), offset - safepointIndices_.back().displacement() >= sizeof(uint32_t)); masm.propagateOOM(safepointIndices_.append(SafepointIndex(offset, ins->safepoint()))); } diff --git a/memory/replace/dmd/DMD.cpp b/memory/replace/dmd/DMD.cpp index ba104dd38b..4f5914f553 100644 --- a/memory/replace/dmd/DMD.cpp +++ b/memory/replace/dmd/DMD.cpp @@ -27,7 +27,7 @@ #endif #include "nscore.h" -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" #include "js/HashTable.h" #include "js/Vector.h" @@ -117,7 +117,7 @@ static bool gIsDMDInitialized = false; // - Indirect allocations in js::{Vector,HashSet,HashMap} -- this class serves // as their AllocPolicy. // -// - Other indirect allocations (e.g. NS_StackWalk) -- see the comments on +// - Other indirect allocations (e.g. MozStackWalk) -- see the comments on // Thread::mBlockIntercepts and in replace_malloc for how these work. // // It would be nice if we could use the InfallibleAllocPolicy from mozalloc, @@ -504,7 +504,7 @@ class Thread // When true, this blocks intercepts, which allows malloc interception // functions to themselves call malloc. (Nb: for direct calls to malloc we // can just use InfallibleAllocPolicy::{malloc_,new_}, but we sometimes - // indirectly call vanilla malloc via functions like NS_StackWalk.) + // indirectly call vanilla malloc via functions like MozStackWalk.) bool mBlockIntercepts; Thread() @@ -727,40 +727,23 @@ StackTrace::Get(Thread* aT) MOZ_ASSERT(gStateLock->IsLocked()); MOZ_ASSERT(aT->InterceptsAreBlocked()); - // On Windows, NS_StackWalk can acquire a lock from the shared library + // On Windows, MozStackWalk can acquire a lock from the shared library // loader. Another thread might call malloc while holding that lock (when // loading a shared library). So we can't be in gStateLock during the call - // to NS_StackWalk. For details, see + // to MozStackWalk. For details, see // https://bugzilla.mozilla.org/show_bug.cgi?id=374829#c8 // On Linux, something similar can happen; see bug 824340. // So let's just release it on all platforms. - nsresult rv; StackTrace tmp; { AutoUnlockState unlock; uint32_t skipFrames = 2; - rv = NS_StackWalk(StackWalkCallback, skipFrames, - gOptions->MaxFrames(), &tmp, 0, nullptr); - } - - if (rv == NS_OK) { - // Handle the common case first. All is ok. Nothing to do. - } else if (rv == NS_ERROR_NOT_IMPLEMENTED || rv == NS_ERROR_FAILURE) { - tmp.mLength = 0; - } else if (rv == NS_ERROR_UNEXPECTED) { - // XXX: This |rv| only happens on Mac, and it indicates that we're handling - // a call to malloc that happened inside a mutex-handling function. Any - // attempt to create a semaphore (which can happen in printf) could - // deadlock. - // - // However, the most complex thing DMD does after Get() returns is to put - // something in a hash table, which might call - // InfallibleAllocPolicy::malloc_. I'm not yet sure if this needs special - // handling, hence the forced abort. Sorry. If you hit this, please file - // a bug and CC nnethercote. - MOZ_CRASH("unexpected case in StackTrace::Get()"); - } else { - MOZ_CRASH("impossible case in StackTrace::Get()"); + if (MozStackWalk(StackWalkCallback, skipFrames, + gOptions->MaxFrames(), &tmp, 0, nullptr)) { + // Handle the common case first. All is ok. Nothing to do. + } else { + tmp.mLength = 0; + } } StackTraceTable::AddPtr p = gStackTraceTable->lookupForAdd(&tmp); @@ -1224,7 +1207,7 @@ replace_malloc(size_t aSize) Thread* t = Thread::Fetch(); if (t->InterceptsAreBlocked()) { // Intercepts are blocked, which means this must be a call to malloc - // triggered indirectly by DMD (e.g. via NS_StackWalk). Be infallible. + // triggered indirectly by DMD (e.g. via MozStackWalk). Be infallible. return InfallibleAllocPolicy::malloc_(aSize); } @@ -1530,9 +1513,9 @@ Init(const malloc_table_t* aMallocTable) // (prior to the creation of any mutexes, apparently) otherwise we can get // hangs when getting stack traces (bug 821577). But // StackWalkInitCriticalAddress() isn't exported from xpcom/, so instead we - // just call NS_StackWalk, because that calls StackWalkInitCriticalAddress(). + // just call MozStackWalk, because that calls StackWalkInitCriticalAddress(). // See the comment above StackWalkInitCriticalAddress() for more details. - (void)NS_StackWalk(NopStackWalkCallback, /* skipFrames */ 0, + (void)MozStackWalk(NopStackWalkCallback, /* skipFrames */ 0, /* maxFrames */ 1, nullptr, 0, nullptr); #endif diff --git a/memory/replace/dmd/moz.build b/memory/replace/dmd/moz.build index 3c08e77c3d..0766c83555 100644 --- a/memory/replace/dmd/moz.build +++ b/memory/replace/dmd/moz.build @@ -13,7 +13,7 @@ EXPORTS += [ SOURCES += [ '../../../mfbt/HashFunctions.cpp', '../../../mfbt/JSONWriter.cpp', - '../../../xpcom/base/nsStackWalk.cpp', + '../../../mozglue/misc/StackWalk.cpp', 'DMD.cpp', ] diff --git a/xpcom/base/nsStackWalk.cpp b/mozglue/misc/StackWalk.cpp similarity index 92% rename from xpcom/base/nsStackWalk.cpp rename to mozglue/misc/StackWalk.cpp index 6cffec12e3..78d452a719 100644 --- a/xpcom/base/nsStackWalk.cpp +++ b/mozglue/misc/StackWalk.cpp @@ -9,9 +9,6 @@ #include "mozilla/Assertions.h" #include "mozilla/IntegerPrintfMacros.h" #include "mozilla/StackWalk.h" -#include "nsStackWalkPrivate.h" - -#include "nsStackWalk.h" #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf @@ -38,16 +35,16 @@ static CriticalAddress gCriticalAddress; #include #endif -#define NSSTACKWALK_SUPPORTS_MACOSX \ +#define MOZ_STACKWALK_SUPPORTS_MACOSX \ (defined(XP_DARWIN) && \ (defined(__i386) || defined(__ppc__) || defined(HAVE__UNWIND_BACKTRACE))) -#define NSSTACKWALK_SUPPORTS_LINUX \ +#define MOZ_STACKWALK_SUPPORTS_LINUX \ (defined(linux) && \ ((defined(__GNUC__) && (defined(__i386) || defined(PPC))) || \ defined(HAVE__UNWIND_BACKTRACE))) -#if NSSTACKWALK_SUPPORTS_MACOSX +#if MOZ_STACKWALK_SUPPORTS_MACOSX #include #include #ifdef MOZ_WIDGET_COCOA @@ -110,7 +107,7 @@ my_malloc_logger(uint32_t aType, // On Leopard dladdr returns the wrong value for "new_sem_from_pool". The // stack shows up as having two pthread_cond_wait$UNIX2003 frames. const char* name = "new_sem_from_pool"; - NS_StackWalk(stack_callback, /* skipFrames */ 0, /* maxFrames */ 0, + MozStackWalk(stack_callback, /* skipFrames */ 0, /* maxFrames */ 0, const_cast(name), 0, nullptr); } @@ -121,7 +118,7 @@ my_malloc_logger(uint32_t aType, // function during NS_LogInit() ensures that we meet the first criterion, and // running this function during the stack walking functions ensures we meet the // second criterion. -void +MFBT_API void StackWalkInitCriticalAddress() { if (gCriticalAddress.mInit) { @@ -181,7 +178,7 @@ IsCriticalAddress(void* aPC) // We still initialize gCriticalAddress.mInit so that this code behaves // the same on all platforms. Otherwise a failure to init would be visible // only on OS X. -void +MFBT_API void StackWalkInitCriticalAddress() { gCriticalAddress.mInit = true; @@ -190,15 +187,12 @@ StackWalkInitCriticalAddress() #if defined(_WIN32) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64)) // WIN32 x86 stack walking code -#include "nscore.h" #include #include #include #include -#include "plstr.h" #include "mozilla/ArrayUtils.h" -#include "nspr.h" #include // We need a way to know if we are building for WXP (or later), as if we are, we // need to use the newer 64-bit APIs. API_VERSION_NUMBER seems to fit the bill. @@ -512,8 +506,8 @@ WalkStackThread(void* aData) * whose in memory address doesn't match its in-file address. */ -XPCOM_API(nsresult) -NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, +MFBT_API bool +MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames, uint32_t aMaxFrames, void* aClosure, uintptr_t aThread, void* aPlatformData) { @@ -524,7 +518,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, struct WalkStackData data; if (!EnsureWalkThreadReady()) { - return NS_ERROR_FAILURE; + return false; } HANDLE currentThread = ::GetCurrentThread(); @@ -542,7 +536,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, if (data.walkCallingThread) { PrintError("DuplicateHandle (process)"); } - return NS_ERROR_FAILURE; + return false; } } if (!::DuplicateHandle(::GetCurrentProcess(), @@ -553,7 +547,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, if (data.walkCallingThread) { PrintError("DuplicateHandle (thread)"); } - return NS_ERROR_FAILURE; + return false; } data.skipFrames = aSkipFrames; @@ -622,7 +616,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, (*aCallback)(i + 1, data.pcs[i], data.sps[i], aClosure); } - return data.pc_count == 0 ? NS_ERROR_FAILURE : NS_OK; + return data.pc_count != 0; } @@ -772,8 +766,8 @@ EnsureSymInitialized() } -XPCOM_API(nsresult) -NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails) +MFBT_API bool +MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails) { aDetails->library[0] = '\0'; aDetails->loffset = 0; @@ -783,7 +777,7 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails) aDetails->foffset = 0; if (!EnsureSymInitialized()) { - return NS_ERROR_FAILURE; + return false; } HANDLE myProcess = ::GetCurrentProcess(); @@ -804,12 +798,12 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails) modInfoRes = SymGetModuleInfoEspecial64(myProcess, addr, &modInfo, &lineInfo); if (modInfoRes) { - PL_strncpyz(aDetails->library, modInfo.ModuleName, + strncpy(aDetails->library, modInfo.ModuleName, sizeof(aDetails->library)); aDetails->loffset = (char*)aPC - (char*)modInfo.BaseOfImage; if (lineInfo.FileName) { - PL_strncpyz(aDetails->filename, lineInfo.FileName, + strncpy(aDetails->filename, lineInfo.FileName, sizeof(aDetails->filename)); aDetails->lineno = lineInfo.LineNumber; } @@ -825,23 +819,21 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails) ok = SymFromAddr(myProcess, addr, &displacement, pSymbol); if (ok) { - PL_strncpyz(aDetails->function, pSymbol->Name, + strncpy(aDetails->function, pSymbol->Name, sizeof(aDetails->function)); aDetails->foffset = static_cast(displacement); } LeaveCriticalSection(&gDbgHelpCS); // release our lock - return NS_OK; + return true; } // i386 or PPC Linux stackwalking code -#elif HAVE_DLADDR && (HAVE__UNWIND_BACKTRACE || NSSTACKWALK_SUPPORTS_LINUX || NSSTACKWALK_SUPPORTS_MACOSX) +#elif HAVE_DLADDR && (HAVE__UNWIND_BACKTRACE || MOZ_STACKWALK_SUPPORTS_LINUX || MOZ_STACKWALK_SUPPORTS_MACOSX) #include #include -#include "nscore.h" #include -#include "plstr.h" // On glibc 2.1, the Dl_info api defined in is only exposed // if __USE_GNU is defined. I suppose its some kind of standards @@ -868,7 +860,7 @@ void DemangleSymbol(const char* aSymbol, char* demangled = abi::__cxa_demangle(aSymbol, 0, 0, 0); if (demangled) { - PL_strncpyz(aBuffer, demangled, aBufLen); + strncpy(aBuffer, demangled, aBufLen); free(demangled); } #endif // MOZ_DEMANGLE_SYMBOLS @@ -884,8 +876,8 @@ void DemangleSymbol(const char* aSymbol, extern MOZ_EXPORT void* __libc_stack_end; // from ld-linux.so #endif namespace mozilla { -nsresult -FramePointerStackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, +bool +FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames, uint32_t aMaxFrames, void* aClosure, void** bp, void* aStackEnd) { @@ -915,7 +907,7 @@ FramePointerStackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, bp += 2; #endif if (IsCriticalAddress(pc)) { - return NS_ERROR_UNEXPECTED; + return false; } if (--skip < 0) { // Assume that the SP points to the BP of the function @@ -930,16 +922,16 @@ FramePointerStackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, } bp = next; } - return numFrames == 0 ? NS_ERROR_FAILURE : NS_OK; + return numFrames != 0; } } #define X86_OR_PPC (defined(__i386) || defined(PPC) || defined(__ppc__)) -#if X86_OR_PPC && (NSSTACKWALK_SUPPORTS_MACOSX || NSSTACKWALK_SUPPORTS_LINUX) // i386 or PPC Linux or Mac stackwalking code +#if X86_OR_PPC && (MOZ_STACKWALK_SUPPORTS_MACOSX || MOZ_STACKWALK_SUPPORTS_LINUX) // i386 or PPC Linux or Mac stackwalking code -XPCOM_API(nsresult) -NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, +MFBT_API bool +MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames, uint32_t aMaxFrames, void* aClosure, uintptr_t aThread, void* aPlatformData) { @@ -975,7 +967,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, struct unwind_info { - NS_WalkStackCallback callback; + MozWalkStackCallback callback; int skip; int maxFrames; int numFrames; @@ -1007,8 +999,8 @@ unwind_callback(struct _Unwind_Context* context, void* closure) return _URC_NO_REASON; } -XPCOM_API(nsresult) -NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, +MFBT_API bool +MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames, uint32_t aMaxFrames, void* aClosure, uintptr_t aThread, void* aPlatformData) { @@ -1034,15 +1026,15 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, // is to make unwind_callback return something other than _URC_NO_REASON, // which causes _Unwind_Backtrace to return a non-success code. if (info.isCriticalAbort) { - return NS_ERROR_UNEXPECTED; + return false; } - return info.numFrames == 0 ? NS_ERROR_FAILURE : NS_OK; + return info.numFrames != 0; } #endif -XPCOM_API(nsresult) -NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails) +bool MFBT_API +MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails) { aDetails->library[0] = '\0'; aDetails->loffset = 0; @@ -1054,51 +1046,51 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails) Dl_info info; int ok = dladdr(aPC, &info); if (!ok) { - return NS_OK; + return true; } - PL_strncpyz(aDetails->library, info.dli_fname, sizeof(aDetails->library)); + strncpy(aDetails->library, info.dli_fname, sizeof(aDetails->library)); aDetails->loffset = (char*)aPC - (char*)info.dli_fbase; const char* symbol = info.dli_sname; if (!symbol || symbol[0] == '\0') { - return NS_OK; + return true; } DemangleSymbol(symbol, aDetails->function, sizeof(aDetails->function)); if (aDetails->function[0] == '\0') { // Just use the mangled symbol if demangling failed. - PL_strncpyz(aDetails->function, symbol, sizeof(aDetails->function)); + strncpy(aDetails->function, symbol, sizeof(aDetails->function)); } aDetails->foffset = (char*)aPC - (char*)info.dli_saddr; - return NS_OK; + return true; } #else // unsupported platform. -XPCOM_API(nsresult) -NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, +MFBT_API bool +MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames, uint32_t aMaxFrames, void* aClosure, uintptr_t aThread, void* aPlatformData) { MOZ_ASSERT(!aThread); MOZ_ASSERT(!aPlatformData); - return NS_ERROR_NOT_IMPLEMENTED; + return false; } namespace mozilla { -nsresult -FramePointerStackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, +MFBT_API bool +FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames, void* aClosure, void** aBp) { - return NS_ERROR_NOT_IMPLEMENTED; + return false; } } -XPCOM_API(nsresult) -NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails) +MFBT_API bool +MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails) { aDetails->library[0] = '\0'; aDetails->loffset = 0; @@ -1106,24 +1098,24 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails) aDetails->lineno = 0; aDetails->function[0] = '\0'; aDetails->foffset = 0; - return NS_ERROR_NOT_IMPLEMENTED; + return false; } #endif -XPCOM_API(void) -NS_FormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize, +MFBT_API void +MozFormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber, void* aPC, - const nsCodeAddressDetails* aDetails) + const MozCodeAddressDetails* aDetails) { - NS_FormatCodeAddress(aBuffer, aBufferSize, + MozFormatCodeAddress(aBuffer, aBufferSize, aFrameNumber, aPC, aDetails->function, aDetails->library, aDetails->loffset, aDetails->filename, aDetails->lineno); } -XPCOM_API(void) -NS_FormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber, +MFBT_API void +MozFormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber, const void* aPC, const char* aFunction, const char* aLibrary, ptrdiff_t aLOffset, const char* aFileName, uint32_t aLineNo) diff --git a/xpcom/base/nsStackWalk.h b/mozglue/misc/StackWalk.h similarity index 78% rename from xpcom/base/nsStackWalk.h rename to mozglue/misc/StackWalk.h index addc032d7a..4546f62d8c 100644 --- a/xpcom/base/nsStackWalk.h +++ b/mozglue/misc/StackWalk.h @@ -6,20 +6,16 @@ /* API for getting a stack trace of the C/C++ stack on the current thread */ -#ifndef nsStackWalk_h_ -#define nsStackWalk_h_ +#ifndef mozilla_StackWalk_h +#define mozilla_StackWalk_h /* WARNING: This file is intended to be included from C or C++ files. */ -#include "nscore.h" +#include "mozilla/Types.h" #include -#ifdef __cplusplus -extern "C" { -#endif - /** - * The callback for NS_StackWalk. + * The callback for MozStackWalk. * * @param aFrameNumber The frame number (starts at 1, not 0). * @param aPC The program counter value. @@ -27,20 +23,20 @@ extern "C" { * pointer will be pointing to when the execution returns * to executing that at aPC. If no approximation can * be made it will be nullptr. - * @param aClosure Extra data passed in via NS_StackWalk(). + * @param aClosure Extra data passed in via MozStackWalk(). */ typedef void -(*NS_WalkStackCallback)(uint32_t aFrameNumber, void* aPC, void* aSP, +(*MozWalkStackCallback)(uint32_t aFrameNumber, void* aPC, void* aSP, void* aClosure); /** * Call aCallback for the C/C++ stack frames on the current thread, from - * the caller of NS_StackWalk to main (or above). + * the caller of MozStackWalk to main (or above). * * @param aCallback Callback function, called once per frame. * @param aSkipFrames Number of initial frames to skip. 0 means that * the first callback will be for the caller of - * NS_StackWalk. + * MozStackWalk. * @param aMaxFrames Maximum number of frames to trace. 0 means no limit. * @param aClosure Caller-supplied data passed through to aCallback. * @param aThread The thread for which the stack is to be retrieved. @@ -53,27 +49,14 @@ typedef void * CONTEXT on Windows and should not be passed on other * platforms. * - * Return values: - * - NS_ERROR_NOT_IMPLEMENTED. Occurs on platforms where it is unimplemented. - * - * - NS_ERROR_UNEXPECTED. Occurs when the stack indicates that the thread - * is in a very dangerous situation (e.g., holding sem_pool_lock in Mac OS X - * pthreads code). Callers should then bail out immediately. - * - * - NS_ERROR_FAILURE. Occurs when stack walking completely failed, i.e. - * aCallback was never called. - * - * - NS_OK. Occurs when stack walking succeeded, i.e. aCallback was called at - * least once (and there was no need to exit with NS_ERROR_UNEXPECTED). - * * May skip some stack frames due to compiler optimizations or code * generation. * * Note: this (and other helper methods) will only be available when * MOZ_STACKWALKING is defined, so any new consumers must #if based on that. */ -XPCOM_API(nsresult) -NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, +MFBT_API bool +MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames, uint32_t aMaxFrames, void* aClosure, uintptr_t aThread, void* aPlatformData); @@ -99,7 +82,7 @@ typedef struct */ char function[256]; ptrdiff_t foffset; -} nsCodeAddressDetails; +} MozCodeAddressDetails; /** * For a given pointer to code, fill in the pieces of information used @@ -108,8 +91,8 @@ typedef struct * @param aPC The code address. * @param aDetails A structure to be filled in with the result. */ -XPCOM_API(nsresult) -NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails); +MFBT_API bool +MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails); /** * Format the information about a code address in a format suitable for @@ -137,15 +120,15 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails); * @param aFileName The filename. Possibly null or the empty string. * @param aLineNo The line number. Possibly zero. */ -XPCOM_API(void) -NS_FormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber, +MFBT_API void +MozFormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber, const void* aPC, const char* aFunction, const char* aLibrary, ptrdiff_t aLOffset, const char* aFileName, uint32_t aLineNo); /** * Format the information about a code address in the same fashion as - * NS_FormatCodeAddress. + * MozFormatCodeAddress. * * @param aBuffer A string to be filled in with the description. * The string will always be null-terminated. @@ -156,15 +139,27 @@ NS_FormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber, * is the terminating null. * @param aFrameNumber The frame number. * @param aPC The code address. - * @param aDetails The value filled in by NS_DescribeCodeAddress(aPC). + * @param aDetails The value filled in by MozDescribeCodeAddress(aPC). */ -XPCOM_API(void) -NS_FormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize, +MFBT_API void +MozFormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber, void* aPC, - const nsCodeAddressDetails* aDetails); + const MozCodeAddressDetails* aDetails); + +namespace mozilla { + +MFBT_API bool +FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames, + uint32_t aMaxFrames, void* aClosure, void** aBp, + void* aStackEnd); -#ifdef __cplusplus } -#endif -#endif /* !defined(nsStackWalk_h_) */ +/** + * Initialize the critical sections for this platform so that we can + * abort stack walks when needed. + */ +MFBT_API void +StackWalkInitCriticalAddress(void); + +#endif diff --git a/mozglue/misc/moz.build b/mozglue/misc/moz.build index 0836fb0c5f..eb71ffe4b6 100644 --- a/mozglue/misc/moz.build +++ b/mozglue/misc/moz.build @@ -1,6 +1,7 @@ FINAL_LIBRARY = 'mozglue' EXPORTS.mozilla += [ + 'StackWalk.h', 'TimeStamp.h', ] @@ -26,6 +27,7 @@ if CONFIG['OS_ARCH'] == 'WINNT': SOURCES += [ 'TimeStamp_windows.cpp', ] + OS_LIBS += ['dbghelp'] elif CONFIG['HAVE_CLOCK_MONOTONIC']: SOURCES += [ 'TimeStamp_posix.cpp', @@ -37,4 +39,14 @@ elif CONFIG['OS_ARCH'] == 'Darwin': elif CONFIG['COMPILE_ENVIRONMENT']: error('No TimeStamp implementation on this platform. Build will not succeed') +# MOZ_STACKWALKING is defined in configure.in when the build configuration meets +# the conditions for GeckoStackWalk to work correctly. +# We exclude this file from other build configurations so that if somebody adds a +# new usage of NS_StackWalk it will cause a link error, which is better than having +# GeckoStackWalk silently return garbage at runtime. +if CONFIG['MOZ_STACKWALKING']: + SOURCES += [ + 'StackWalk.cpp', + ] + FAIL_ON_WARNINGS = True diff --git a/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h b/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h index fe1abd25d3..5ce5689bde 100644 --- a/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h +++ b/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h @@ -18,7 +18,7 @@ #include "nsContentUtils.h" #ifdef MOZ_STACKWALKING -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" #endif #define TARGET_SANDBOX_EXPORT __declspec(dllexport) @@ -63,10 +63,10 @@ StackFrameToOStringStream(uint32_t aFrameNumber, void* aPC, void* aSP, void* aClosure) { std::ostringstream* stream = static_cast(aClosure); - nsCodeAddressDetails details; + MozCodeAddressDetails details; char buf[1024]; - NS_DescribeCodeAddress(aPC, &details); - NS_FormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details); + MozDescribeCodeAddress(aPC, &details); + MozFormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details); *stream << std::endl << "--" << buf; stream->flush(); } @@ -90,7 +90,7 @@ Log(const char* aMessageType, if (aShouldLogStackTrace) { if (sStackTraceDepth) { msgStream << std::endl << "Stack Trace:"; - NS_StackWalk(StackFrameToOStringStream, aFramesToSkip, sStackTraceDepth, + MozStackWalk(StackFrameToOStringStream, aFramesToSkip, sStackTraceDepth, &msgStream, 0, nullptr); } } diff --git a/security/sandbox/linux/glue/SandboxCrash.cpp b/security/sandbox/linux/glue/SandboxCrash.cpp index a8513e21ef..81efdbc537 100644 --- a/security/sandbox/linux/glue/SandboxCrash.cpp +++ b/security/sandbox/linux/glue/SandboxCrash.cpp @@ -18,7 +18,7 @@ #include "mozilla/unused.h" #include "mozilla/dom/Exceptions.h" #include "nsContentUtils.h" -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" #include "nsString.h" #include "nsThreadUtils.h" @@ -74,10 +74,10 @@ static void SandboxPrintStackFrame(uint32_t aFrameNumber, void *aPC, void *aSP, void *aClosure) { char buf[1024]; - nsCodeAddressDetails details; + MozCodeAddressDetails details; - NS_DescribeCodeAddress(aPC, &details); - NS_FormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details); + MozDescribeCodeAddress(aPC, &details); + MozFormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details); SANDBOX_LOG_ERROR("frame %s", buf); } @@ -87,11 +87,11 @@ SandboxLogCStack() // Skip 3 frames: one for this module, one for the signal handler in // libmozsandbox, and one for the signal trampoline. // - // Warning: this might not print any stack frames. NS_StackWalk + // Warning: this might not print any stack frames. MozStackWalk // can't walk past the signal trampoline on ARM (bug 968531), and // x86 frame pointer walking may or may not work (bug 1082276). - NS_StackWalk(SandboxPrintStackFrame, /* skip */ 3, /* max */ 0, + MozStackWalk(SandboxPrintStackFrame, /* skip */ 3, /* max */ 0, nullptr, 0, nullptr); SANDBOX_LOG_ERROR("end of stack."); } diff --git a/toolkit/xre/nsSigHandlers.cpp b/toolkit/xre/nsSigHandlers.cpp index 26aa9ef573..fa1150ff64 100644 --- a/toolkit/xre/nsSigHandlers.cpp +++ b/toolkit/xre/nsSigHandlers.cpp @@ -58,7 +58,7 @@ unsigned int _gdb_sleep_duration = 300; #include #include "nsISupportsUtils.h" -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" // NB: keep me up to date with the same variable in // ipc/chromium/chrome/common/ipc_channel_posix.cc @@ -70,10 +70,10 @@ static void PrintStackFrame(uint32_t aFrameNumber, void *aPC, void *aSP, void *aClosure) { char buf[1024]; - nsCodeAddressDetails details; + MozCodeAddressDetails details; - NS_DescribeCodeAddress(aPC, &details); - NS_FormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details); + MozDescribeCodeAddress(aPC, &details); + MozFormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details); fprintf(stdout, "%s\n", buf); fflush(stdout); } @@ -89,7 +89,7 @@ ah_crap_handler(int signum) signum); printf("Stack:\n"); - NS_StackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0, + MozStackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0, nullptr, 0, nullptr); printf("Sleeping for %d seconds.\n",_gdb_sleep_duration); diff --git a/tools/profiler/GeckoProfilerFunc.h b/tools/profiler/GeckoProfilerFunc.h index 3f017e6f13..1e2764a6e1 100644 --- a/tools/profiler/GeckoProfilerFunc.h +++ b/tools/profiler/GeckoProfilerFunc.h @@ -38,6 +38,7 @@ bool mozilla_sampler_is_active(); void mozilla_sampler_responsiveness(TimeStamp time); void mozilla_sampler_frame_number(int frameNumber); const double* mozilla_sampler_get_responsiveness(); + void mozilla_sampler_save(); mozilla::UniquePtr mozilla_sampler_get_profile(float aSinceTime); @@ -46,6 +47,12 @@ JSObject *mozilla_sampler_get_profile_data(JSContext *aCx, float aSinceTime); void mozilla_sampler_get_profile_data_async(float aSinceTime, mozilla::dom::Promise* aPromise); +// Make this function easily callable from a debugger in a build without +// debugging information (work around http://llvm.org/bugs/show_bug.cgi?id=22211) +extern "C" { + void mozilla_sampler_save_profile_to_file(const char* aFilename); +} + const char** mozilla_sampler_get_features(); void mozilla_sampler_get_buffer_info(uint32_t *aCurrentPosition, uint32_t *aTotalSize, diff --git a/tools/profiler/ProfileEntry.cpp b/tools/profiler/ProfileEntry.cpp index 7a5666d74a..f878cfd3bf 100644 --- a/tools/profiler/ProfileEntry.cpp +++ b/tools/profiler/ProfileEntry.cpp @@ -111,11 +111,21 @@ ProfileBuffer::ProfileBuffer(int aEntrySize) { } +ProfileBuffer::~ProfileBuffer() +{ + while (mStoredMarkers.peek()) { + delete mStoredMarkers.popHead(); + } +} + // Called from signal, call only reentrant functions void ProfileBuffer::addTag(const ProfileEntry& aTag) { mEntries[mWritePos++] = aTag; if (mWritePos == mEntrySize) { + // Wrapping around may result in things referenced in the buffer (e.g., + // JIT code addresses and markers) being incorrectly collected. + MOZ_ASSERT(mGeneration != UINT32_MAX); mGeneration++; mWritePos = 0; } @@ -134,7 +144,7 @@ void ProfileBuffer::addStoredMarker(ProfilerMarker *aStoredMarker) { void ProfileBuffer::deleteExpiredStoredMarkers() { // Delete markers of samples that have been overwritten due to circular // buffer wraparound. - int generation = mGeneration; + uint32_t generation = mGeneration; while (mStoredMarkers.peek() && mStoredMarkers.peek()->HasExpired(generation)) { delete mStoredMarkers.popHead(); diff --git a/tools/profiler/ProfileEntry.h b/tools/profiler/ProfileEntry.h index e6ed4f400a..e211389b67 100644 --- a/tools/profiler/ProfileEntry.h +++ b/tools/profiler/ProfileEntry.h @@ -250,7 +250,7 @@ protected: char* processDynamicTag(int readPos, int* tagsConsumed, char* tagBuff); int FindLastSampleOfThread(int aThreadId); - ~ProfileBuffer() {} + ~ProfileBuffer(); public: // Circular buffer 'Keep One Slot Open' implementation for simplicity @@ -267,7 +267,7 @@ public: int mEntrySize; // How many times mWritePos has wrapped around. - int mGeneration; + uint32_t mGeneration; // Markers that marker entries in the buffer might refer to. ProfilerMarkerLinkedList mStoredMarkers; @@ -410,7 +410,6 @@ public: } uint32_t bufferGeneration() const { - MOZ_ASSERT(mBuffer->mGeneration >= 0); return mBuffer->mGeneration; } diff --git a/tools/profiler/PseudoStack.h b/tools/profiler/PseudoStack.h index 1ebf56cd39..d6a2ac7733 100644 --- a/tools/profiler/PseudoStack.h +++ b/tools/profiler/PseudoStack.h @@ -92,9 +92,9 @@ public: void StreamJSON(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks) const; - void SetGeneration(int aGenID); + void SetGeneration(uint32_t aGenID); - bool HasExpired(int aGenID) const { + bool HasExpired(uint32_t aGenID) const { return mGenID + 2 <= aGenID; } @@ -105,7 +105,7 @@ private: ProfilerMarkerPayload* mPayload; ProfilerMarker* mNext; float mTime; - int mGenID; + uint32_t mGenID; }; template diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index d01bef05b5..08688d4949 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -47,9 +47,6 @@ #if defined(MOZ_PROFILING) && (defined(XP_MACOSX) || defined(XP_WIN)) #define USE_NS_STACKWALK #endif -#ifdef USE_NS_STACKWALK - #include "nsStackWalk.h" -#endif #if defined(XP_WIN) typedef CONTEXT tickcontext_t; @@ -635,7 +632,16 @@ void mergeStacksIntoProfile(ThreadProfile& aProfile, TickSample* aSample, Native // like the native stack, the JS stack is iterated youngest-to-oldest and we // need to iterate oldest-to-youngest when adding entries to aProfile. - uint32_t startBufferGen = aProfile.bufferGeneration(); + // Synchronous sampling reports an invalid buffer generation to + // ProfilingFrameIterator to avoid incorrectly resetting the generation of + // sampled JIT entries inside the JS engine. See note below concerning 'J' + // entries. + uint32_t startBufferGen; + if (aSample->isSamplingCurrentThread) { + startBufferGen = UINT32_MAX; + } else { + startBufferGen = aProfile.bufferGeneration(); + } uint32_t jsCount = 0; JS::ProfilingFrameIterator::Frame jsFrames[1000]; // Only walk jit stack if profiling frame iterator is turned on. @@ -781,14 +787,13 @@ void mergeStacksIntoProfile(ThreadProfile& aProfile, TickSample* aSample, Native } } - MOZ_ASSERT(aProfile.bufferGeneration() >= startBufferGen); - uint32_t lapCount = aProfile.bufferGeneration() - startBufferGen; - // Update the JS runtime with the current profile sample buffer generation. // // Do not do this for synchronous sampling, which create their own // ProfileBuffers. if (!aSample->isSamplingCurrentThread && pseudoStack->mRuntime) { + MOZ_ASSERT(aProfile.bufferGeneration() >= startBufferGen); + uint32_t lapCount = aProfile.bufferGeneration() - startBufferGen; JS::UpdateJSRuntimeProfilerSampleBufferGen(pseudoStack->mRuntime, aProfile.bufferGeneration(), lapCount); @@ -823,7 +828,7 @@ void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample }; // Start with the current function. We use 0 as the frame number here because - // the FramePointerStackWalk() and NS_StackWalk() calls below will use 1..N. + // the FramePointerStackWalk() and MozStackWalk() calls below will use 1..N. // This is a bit weird but it doesn't matter because StackWalkCallback() // doesn't use the frame number argument. StackWalkCallback(/* frameNumber */ 0, aSample->pc, aSample->sp, &nativeStack); @@ -834,7 +839,7 @@ void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample void *stackEnd = reinterpret_cast(-1); if (pt) stackEnd = static_cast(pthread_get_stackaddr_np(pt)); - nsresult rv = NS_OK; + bool rv = true; if (aSample->fp >= aSample->sp && aSample->fp <= stackEnd) rv = FramePointerStackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames, &nativeStack, @@ -843,17 +848,17 @@ void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample void *platformData = nullptr; #ifdef XP_WIN if (aSample->isSamplingCurrentThread) { - // In this case we want NS_StackWalk to know that it's walking the + // In this case we want MozStackWalk to know that it's walking the // current thread's stack, so we pass 0 as the thread handle. thread = 0; } platformData = aSample->context; #endif // XP_WIN - nsresult rv = NS_StackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames, + bool rv = MozStackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames, &nativeStack, thread, platformData); #endif - if (NS_SUCCEEDED(rv)) + if (rv) mergeStacksIntoProfile(aProfile, aSample, nativeStack); } #endif diff --git a/tools/profiler/platform.cpp b/tools/profiler/platform.cpp index f60dd7e615..a7ef966771 100644 --- a/tools/profiler/platform.cpp +++ b/tools/profiler/platform.cpp @@ -197,7 +197,7 @@ ProfilerMarker::~ProfilerMarker() { } void -ProfilerMarker::SetGeneration(int aGenID) { +ProfilerMarker::SetGeneration(uint32_t aGenID) { mGenID = aGenID; } diff --git a/xpcom/base/CodeAddressService.h b/xpcom/base/CodeAddressService.h index c6372b6c3e..7f91f93a66 100644 --- a/xpcom/base/CodeAddressService.h +++ b/xpcom/base/CodeAddressService.h @@ -13,7 +13,7 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/Types.h" -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" namespace mozilla { @@ -27,7 +27,7 @@ namespace mozilla { // while |free| is used to free strings created by |copy|. // // |DescribeCodeAddressLock| is needed when the callers may be holding a lock -// used by NS_DescribeCodeAddress. |DescribeCodeAddressLock| must implement +// used by MozDescribeCodeAddress. |DescribeCodeAddressLock| must implement // static methods IsLocked(), Unlock() and Lock(). template (aPc), &details); + (void)MozDescribeCodeAddress(const_cast(aPc), &details); DescribeCodeAddressLock::Lock(); } @@ -159,7 +159,7 @@ public: MOZ_ASSERT(entry.mPc == aPc); - NS_FormatCodeAddress(aBuf, aBufLen, aFrameNumber, entry.mPc, + MozFormatCodeAddress(aBuf, aBufLen, aFrameNumber, entry.mPc, entry.mFunction, entry.mLibrary, entry.mLOffset, entry.mFileName, entry.mLineNo); } diff --git a/xpcom/base/StackWalk.h b/xpcom/base/StackWalk.h deleted file mode 100644 index a3c6b83db0..0000000000 --- a/xpcom/base/StackWalk.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* API for getting a stack trace of the C/C++ */ - -#ifndef StackWalk_h_ -#define StackWalk_h_ - -// XXX: it would be nice to eventually remove this header dependency on nsStackWalk.h -#include "nsStackWalk.h" - -namespace mozilla { - -nsresult -FramePointerStackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames, - uint32_t aMaxFrames, void* aClosure, void** aBp, - void* aStackEnd); - -} - -#endif /* !defined(StackWalk_h_) */ diff --git a/xpcom/base/moz.build b/xpcom/base/moz.build index 3621a45ca6..2034668c49 100644 --- a/xpcom/base/moz.build +++ b/xpcom/base/moz.build @@ -57,7 +57,6 @@ EXPORTS += [ 'nsISupportsBase.h', 'nsObjCExceptions.h', 'nsQueryObject.h', - 'nsStackWalk.h', 'nsTraceRefcnt.h', 'nsWeakPtr.h', ] @@ -79,7 +78,6 @@ EXPORTS.mozilla += [ 'HoldDropJSObjects.h', 'LinuxUtils.h', 'nsMemoryInfoDumper.h', - 'StackWalk.h', 'StaticMutex.h', 'StaticPtr.h', 'SystemMemoryReporter.h', @@ -120,16 +118,6 @@ UNIFIED_SOURCES += [ 'nsVersionComparatorImpl.cpp', ] -# MOZ_STACKWALKING is defined in configure.in when the build configuration meets -# the conditions for NS_StackWalk to work correctly. -# We exclude this file from other build configurations so that if somebody adds a -# new usage of NS_StackWalk it will cause a link error, which is better than having -# NS_StackWalk silently return garbage at runtime. -if CONFIG['MOZ_STACKWALKING']: - SOURCES += [ - 'nsStackWalk.cpp', - ] - if CONFIG['OS_ARCH'] == 'Linux': SOURCES += [ 'LinuxUtils.cpp', diff --git a/xpcom/base/nsStackWalkPrivate.h b/xpcom/base/nsStackWalkPrivate.h deleted file mode 100644 index 9e1041d87a..0000000000 --- a/xpcom/base/nsStackWalkPrivate.h +++ /dev/null @@ -1,12 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Initialize the critical sections for this platform so that we can - * abort stack walks when needed. - */ -void -StackWalkInitCriticalAddress(void); diff --git a/xpcom/base/nsTraceRefcnt.cpp b/xpcom/base/nsTraceRefcnt.cpp index cd75450a2e..9718019211 100644 --- a/xpcom/base/nsTraceRefcnt.cpp +++ b/xpcom/base/nsTraceRefcnt.cpp @@ -18,8 +18,7 @@ #include "nsCRT.h" #include #include "nsHashKeys.h" -#include "nsStackWalkPrivate.h" -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" #include "nsString.h" #include "nsThreadUtils.h" #include "CodeAddressService.h" @@ -210,7 +209,7 @@ struct CodeAddressServiceStringAlloc final static void free(char* aPtr) { ::free(aPtr); } }; -// WalkTheStack does not hold any locks needed by NS_DescribeCodeAddress, so +// WalkTheStack does not hold any locks needed by MozDescribeCodeAddress, so // this class does not need to do anything. struct CodeAddressServiceLock final { @@ -829,11 +828,11 @@ static void PrintStackFrame(uint32_t aFrameNumber, void* aPC, void* aSP, void* aClosure) { FILE* stream = (FILE*)aClosure; - nsCodeAddressDetails details; + MozCodeAddressDetails details; char buf[1024]; - NS_DescribeCodeAddress(aPC, &details); - NS_FormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details); + MozDescribeCodeAddress(aPC, &details); + MozFormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details); fprintf(stream, "%s\n", buf); fflush(stream); } @@ -857,7 +856,7 @@ void nsTraceRefcnt::WalkTheStack(FILE* aStream) { #ifdef MOZ_STACKWALKING - NS_StackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0, aStream, + MozStackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0, aStream, 0, nullptr); #endif } @@ -869,7 +868,7 @@ nsTraceRefcnt::WalkTheStackCached(FILE* aStream) if (!gCodeAddressService) { gCodeAddressService = new WalkTheStackCodeAddressService(); } - NS_StackWalk(PrintStackFrameCached, /* skipFrames */ 2, /* maxFrames */ 0, + MozStackWalk(PrintStackFrameCached, /* skipFrames */ 2, /* maxFrames */ 0, aStream, 0, nullptr); #endif } diff --git a/xpcom/build/LateWriteChecks.cpp b/xpcom/build/LateWriteChecks.cpp index 928e1fe983..25cac9cbac 100644 --- a/xpcom/build/LateWriteChecks.cpp +++ b/xpcom/build/LateWriteChecks.cpp @@ -15,7 +15,7 @@ #include "nsAppDirectoryServiceDefs.h" #include "nsDirectoryServiceUtils.h" #include "nsPrintfCString.h" -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" #include "plstr.h" #include "prio.h" @@ -128,7 +128,7 @@ LateWriteObserver::Observe(IOInterposeObserver::Observation& aOb) // concurrently from many writes, so we use multiple temporary files. std::vector rawStack; - NS_StackWalk(RecordStackWalker, /* skipFrames */ 0, /* maxFrames */ 0, + MozStackWalk(RecordStackWalker, /* skipFrames */ 0, /* maxFrames */ 0, reinterpret_cast(&rawStack), 0, nullptr); nsPrintfCString nameAux("%s%s%s", mProfileDirectory, diff --git a/xpcom/build/PoisonIOInterposerMac.cpp b/xpcom/build/PoisonIOInterposerMac.cpp index ce85def3da..7064a41218 100644 --- a/xpcom/build/PoisonIOInterposerMac.cpp +++ b/xpcom/build/PoisonIOInterposerMac.cpp @@ -15,7 +15,7 @@ #include "mozilla/ProcessedStack.h" #include "mozilla/Scoped.h" #include "nsPrintfCString.h" -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" #include "nsTraceRefcnt.h" #include "plstr.h" #include "prio.h" diff --git a/xpcom/glue/BlockingResourceBase.cpp b/xpcom/glue/BlockingResourceBase.cpp index 887c90a881..6b2ad1df39 100644 --- a/xpcom/glue/BlockingResourceBase.cpp +++ b/xpcom/glue/BlockingResourceBase.cpp @@ -14,7 +14,7 @@ #ifndef MOZ_CALLSTACK_DISABLED #include "CodeAddressService.h" #include "nsHashKeys.h" -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" #include "nsTHashtable.h" #endif @@ -68,7 +68,7 @@ BlockingResourceBase::GetStackTrace(AcquisitionState& aState) // NB: Ignore the return value, there's nothing useful we can do if this // this fails. - NS_StackWalk(StackWalkCallback, kSkipFrames, 24, &aState, 0, nullptr); + MozStackWalk(StackWalkCallback, kSkipFrames, 24, &aState, 0, nullptr); #endif } diff --git a/xpcom/threads/HangMonitor.cpp b/xpcom/threads/HangMonitor.cpp index 2f1b2c4c51..ea004e3f91 100644 --- a/xpcom/threads/HangMonitor.cpp +++ b/xpcom/threads/HangMonitor.cpp @@ -14,7 +14,7 @@ #include "mozilla/StaticPtr.h" #include "mozilla/UniquePtr.h" #include "nsReadableUtils.h" -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" #include "nsThreadUtils.h" #include "nsXULAppAPI.h" diff --git a/xpcom/threads/nsThread.cpp b/xpcom/threads/nsThread.cpp index d0d6a4b599..2334486f90 100644 --- a/xpcom/threads/nsThread.cpp +++ b/xpcom/threads/nsThread.cpp @@ -60,7 +60,7 @@ #if defined(NS_FUNCTION_TIMER) && defined(_MSC_VER) #include "nsTimerImpl.h" -#include "nsStackWalk.h" +#include "mozilla/StackWalk.h" #endif #ifdef NS_FUNCTION_TIMER #include "nsCRT.h"