diff --git a/dom/base/crashtests/637116.html b/dom/base/crashtests/637116.html index e51100082b..01e8cd4180 100644 --- a/dom/base/crashtests/637116.html +++ b/dom/base/crashtests/637116.html @@ -6,7 +6,7 @@ function K(v) { return function() { return v; } } -var errorProxy = Proxy.create({get: function() { throw new Error(); }}); +var errorProxy = new Proxy({}, {get: function() { throw new Error(); }}); function boom() { diff --git a/dom/base/crashtests/695867.html b/dom/base/crashtests/695867.html index d361462dad..4cba753f7b 100644 --- a/dom/base/crashtests/695867.html +++ b/dom/base/crashtests/695867.html @@ -3,7 +3,7 @@ var nodeList = document.documentElement.childNodes; nodeList.__proto__ = null; -var p = Proxy.create({getPropertyDescriptor: function() {return nodeList}}); -p.x; +var p = new Proxy({}, {getOwnPropertyDescriptor: function() {return nodeList}}); +Reflect.getOwnPropertyDescriptor(p, "x"); diff --git a/dom/base/crashtests/708405-1.html b/dom/base/crashtests/708405-1.html deleted file mode 100644 index 9fa92dedea..0000000000 --- a/dom/base/crashtests/708405-1.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - diff --git a/dom/base/crashtests/crashtests.list b/dom/base/crashtests/crashtests.list index 73ad2f1e42..09ca168a74 100644 --- a/dom/base/crashtests/crashtests.list +++ b/dom/base/crashtests/crashtests.list @@ -143,7 +143,6 @@ load 700090-1.html load 700090-2.html load 700512.html load 706283-1.html -load 708405-1.html load 709384.html load 709954.html load 713417-1.html diff --git a/dom/bindings/crashtests/862610.html b/dom/bindings/crashtests/862610.html index 1426ff4a6a..768871ad96 100644 --- a/dom/bindings/crashtests/862610.html +++ b/dom/bindings/crashtests/862610.html @@ -3,7 +3,7 @@ - - - - -Mozilla Bug 1021258 -

- -
-
- - - diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 5c83fa1ca8..91972e7329 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -2817,7 +2817,9 @@ nsDisplayBackgroundImage::ConfigureLayer(ImageLayer* aLayer, // asynchronously, this is not enough. Bug 1183378 will provide a more // complete fix, but this solution is safe in more cases than simply relying // on the intrinsic size. - IntSize containerSize = aLayer->GetContainer()->GetCurrentSize(); + IntSize containerSize = aLayer->GetContainer() + ? aLayer->GetContainer()->GetCurrentSize() + : IntSize(imageWidth, imageHeight); const LayoutDevicePoint p = mImageLayerDestRect.TopLeft(); Matrix transform = Matrix::Translation(p.x, p.y); @@ -3438,12 +3440,16 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder, // are the event targets for any regions viewport frames may cover. return; } + uint8_t pointerEvents = aFrame->StyleVisibility()->GetEffectivePointerEvents(aFrame); if (pointerEvents == NS_STYLE_POINTER_EVENTS_NONE) { return; } - if (!aFrame->StyleVisibility()->IsVisible()) { - return; + bool simpleRegions = aFrame->HasAnyStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS); + if (!simpleRegions) { + if (!aFrame->StyleVisibility()->IsVisible()) { + return; + } } // XXX handle other pointerEvents values for SVG @@ -3462,15 +3468,23 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder, } borderBox += aBuilder->ToReferenceFrame(aFrame); + bool borderBoxHasRoundedCorners = false; + if (!simpleRegions) { + if (nsLayoutUtils::HasNonZeroCorner(aFrame->StyleBorder()->mBorderRadius)) { + borderBoxHasRoundedCorners = true; + } else { + aFrame->AddStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS); + } + } + const DisplayItemClip* clip = aBuilder->ClipState().GetCurrentCombinedClip(aBuilder); - bool borderBoxHasRoundedCorners = - nsLayoutUtils::HasNonZeroCorner(aFrame->StyleBorder()->mBorderRadius); if (clip) { borderBox = clip->ApplyNonRoundedIntersection(borderBox); if (clip->GetRoundedRectCount() > 0) { borderBoxHasRoundedCorners = true; } } + if (borderBoxHasRoundedCorners || (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) { mMaybeHitRegion.Or(mMaybeHitRegion, borderBox); diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 6087dfcb61..19cb567a07 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1411,40 +1411,6 @@ public: static nscoord ComputeCBDependentValue(nscoord aPercentBasis, const nsStyleCoord& aCoord); - /* - * Convert nsStyleCoord to nscoord when percentages depend on the - * containing block width, and enumerated values are for width, - * min-width, or max-width. Returns the content-box width value based - * on aContentEdgeToBoxSizing and aBoxSizingToMarginEdge (which are - * also used for the enumerated values for width. This function does - * not handle 'auto'. It ensures that the result is nonnegative. - * - * @param aRenderingContext Rendering context for font measurement/metrics. - * @param aFrame Frame whose (min-/max-/)width is being computed. - * @param aContainingBlockWidth Width of aFrame's containing block. - * @param aContentEdgeToBoxSizing The sum of any left/right padding and - * border that goes inside the rect chosen by box-sizing. - * @param aBoxSizingToMarginEdge The sum of any left/right padding, border, - * and margin that goes outside the rect chosen by box-sizing. - * @param aCoord The width value to compute. - */ - // XXX to be removed - static nscoord ComputeWidthValue( - nsRenderingContext* aRenderingContext, - nsIFrame* aFrame, - nscoord aContainingBlockWidth, - nscoord aContentEdgeToBoxSizing, - nscoord aBoxSizingToMarginEdge, - const nsStyleCoord& aCoord) - { - return ComputeISizeValue(aRenderingContext, - aFrame, - aContainingBlockWidth, - aContentEdgeToBoxSizing, - aBoxSizingToMarginEdge, - aCoord); - } - static nscoord ComputeISizeValue( nsRenderingContext* aRenderingContext, nsIFrame* aFrame, @@ -1453,35 +1419,10 @@ public: nscoord aBoxSizingToMarginEdge, const nsStyleCoord& aCoord); - /* - * Convert nsStyleCoord to nscoord when percentages depend on the - * containing block height. - */ - // XXX to be removed - static nscoord ComputeHeightDependentValue( - nscoord aContainingBlockHeight, - const nsStyleCoord& aCoord) - { - return ComputeBSizeDependentValue(aContainingBlockHeight, aCoord); - } - static nscoord ComputeBSizeDependentValue( nscoord aContainingBlockBSize, const nsStyleCoord& aCoord); - /* - * Likewise, but for 'height', 'min-height', or 'max-height'. - */ - // XXX to be removed - static nscoord ComputeHeightValue(nscoord aContainingBlockHeight, - nscoord aContentEdgeToBoxSizingBoxEdge, - const nsStyleCoord& aCoord) - { - return ComputeBSizeValue(aContainingBlockHeight, - aContentEdgeToBoxSizingBoxEdge, - aCoord); - } - static nscoord ComputeBSizeValue(nscoord aContainingBlockBSize, nscoord aContentEdgeToBoxSizingBoxEdge, const nsStyleCoord& aCoord) diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 226a292e0a..4530cc6f0c 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -1203,9 +1203,14 @@ nsPresContext::SetShell(nsIPresShell* aShell) } if (IsRoot()) { + nsRootPresContext* thisRoot = static_cast(this); + // Have to cancel our plugin geometry timer, because the // callback for that depends on a non-null presshell. - static_cast(this)->CancelApplyPluginGeometryTimer(); + thisRoot->CancelApplyPluginGeometryTimer(); + + // The did-paint timer also depends on a non-null pres shell. + thisRoot->CancelDidPaintTimer(); } } } diff --git a/layout/base/nsPresState.h b/layout/base/nsPresState.h index eb56c53d73..00f1803053 100644 --- a/layout/base/nsPresState.h +++ b/layout/base/nsPresState.h @@ -25,6 +25,7 @@ public: , mScaleToResolution(false) , mDisabledSet(false) , mDisabled(false) + , mDroppedDown(false) {} void SetScrollState(const nsPoint& aState) @@ -89,6 +90,16 @@ public: mContentData = aProperty; } + void SetDroppedDown(bool aDroppedDown) + { + mDroppedDown = aDroppedDown; + } + + bool GetDroppedDown() const + { + return mDroppedDown; + } + // MEMBER VARIABLES protected: nsCOMPtr mContentData; @@ -97,6 +108,7 @@ protected: bool mScaleToResolution; bool mDisabledSet; bool mDisabled; + bool mDroppedDown; }; #endif /* nsPresState_h_ */ diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 733deb363b..400da24b29 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -912,6 +912,8 @@ nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext) if (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { PresContext()->SetBidiEnabled(); } + + RemoveStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS); } // MSVC fails with link error "one or more multiply defined symbols found", diff --git a/layout/generic/nsFrameStateBits.h b/layout/generic/nsFrameStateBits.h index b22a3feaf2..0b73b453b6 100644 --- a/layout/generic/nsFrameStateBits.h +++ b/layout/generic/nsFrameStateBits.h @@ -180,6 +180,12 @@ FRAME_STATE_BIT(Generic, 33, NS_FRAME_DRAWING_AS_PAINTSERVER) // situation (possibly the frame itself). FRAME_STATE_BIT(Generic, 34, NS_FRAME_DESCENDANT_INTRINSIC_ISIZE_DEPENDS_ON_BSIZE) +// A flag that tells us we can take the common path with respect to style +// properties for this frame when building event regions. This flag is cleared +// when any styles are changed and then we recompute it on the next build +// of the event regions. +FRAME_STATE_BIT(Generic, 35, NS_FRAME_SIMPLE_EVENT_REGIONS) + // Frame is a display root and the retained layer tree needs to be updated // at the next paint via display list construction. // Only meaningful for display roots, so we don't really need a global state diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 35c53fdad9..d05a7ff9ce 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1710,7 +1710,9 @@ nsDisplayImage::ConfigureLayer(ImageLayer* aLayer, // asynchronously, this is not enough. Bug 1183378 will provide a more // complete fix, but this solution is safe in more cases than simply relying // on the intrinsic size. - IntSize containerSize = aLayer->GetContainer()->GetCurrentSize(); + IntSize containerSize = aLayer->GetContainer() + ? aLayer->GetContainer()->GetCurrentSize() + : IntSize(imageWidth, imageHeight); const LayoutDevicePoint p = destRect.TopLeft(); Matrix transform = Matrix::Translation(p.x, p.y); diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 996e38a045..d11891413a 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -17257,27 +17257,6 @@ nsCSSParser::Shutdown() // Wrapper methods -nsresult -nsCSSParser::SetStyleSheet(CSSStyleSheet* aSheet) -{ - return static_cast(mImpl)-> - SetStyleSheet(aSheet); -} - -nsresult -nsCSSParser::SetQuirkMode(bool aQuirkMode) -{ - return static_cast(mImpl)-> - SetQuirkMode(aQuirkMode); -} - -nsresult -nsCSSParser::SetChildLoader(mozilla::css::Loader* aChildLoader) -{ - return static_cast(mImpl)-> - SetChildLoader(aChildLoader); -} - nsresult nsCSSParser::ParseSheet(const nsAString& aInput, nsIURI* aSheetURI, diff --git a/layout/style/nsCSSParser.h b/layout/style/nsCSSParser.h index 2fa600fd62..4ab3c8abed 100644 --- a/layout/style/nsCSSParser.h +++ b/layout/style/nsCSSParser.h @@ -53,29 +53,19 @@ private: nsCSSParser& operator=(nsCSSParser const&) = delete; public: - // Set a style sheet for the parser to fill in. The style sheet must - // implement the CSSStyleSheet interface. Null can be passed in to clear - // out an existing stylesheet reference. - nsresult SetStyleSheet(mozilla::CSSStyleSheet* aSheet); - - // Set whether or not to emulate Nav quirks - nsresult SetQuirkMode(bool aQuirkMode); - - // Set loader to use for child sheets - nsresult SetChildLoader(mozilla::css::Loader* aChildLoader); - /** - * Parse aInput into the stylesheet that was previously set by calling - * SetStyleSheet. Calling this method without calling SetStyleSheet first is - * an error. + * Parse aInput into the stylesheet that was previously passed to the + * constructor. Calling this method on an nsCSSParser that had nullptr + * passed in as the style sheet is an error. * * @param aInput the data to parse * @param aSheetURL the URI to use as the sheet URI (for error reporting). * This must match the URI of the sheet passed to - * SetStyleSheet. + * the constructor. * @param aBaseURI the URI to use for relative URI resolution * @param aSheetPrincipal the principal of the stylesheet. This must match - * the principal of the sheet passed to SetStyleSheet. + * the principal of the sheet passed to the + * constructor. * @param aLineNumber the line number of the first line of the sheet. * @param aParsingMode see SheetParsingMode in css/Loader.h * @param aReusableSheets style sheets that can be reused by an @import. diff --git a/layout/xul/nsImageBoxFrame.cpp b/layout/xul/nsImageBoxFrame.cpp index 9052bc249f..a3d12ce0f7 100644 --- a/layout/xul/nsImageBoxFrame.cpp +++ b/layout/xul/nsImageBoxFrame.cpp @@ -481,7 +481,9 @@ nsDisplayXULImage::ConfigureLayer(ImageLayer* aLayer, // asynchronously, this is not enough. Bug 1183378 will provide a more // complete fix, but this solution is safe in more cases than simply relying // on the intrinsic size. - IntSize containerSize = aLayer->GetContainer()->GetCurrentSize(); + IntSize containerSize = aLayer->GetContainer() + ? aLayer->GetContainer()->GetCurrentSize() + : IntSize(imageWidth, imageHeight); const LayoutDevicePoint p = destRect.TopLeft(); Matrix transform = Matrix::Translation(p.x, p.y); diff --git a/media/libvpx/vp9/common/x86/vp9_subpixel_8t_intrin_avx2.c b/media/libvpx/vp9/common/x86/vp9_subpixel_8t_intrin_avx2.c index 9981f85cdb..cee8d1e76a 100644 --- a/media/libvpx/vp9/common/x86/vp9_subpixel_8t_intrin_avx2.c +++ b/media/libvpx/vp9/common/x86/vp9_subpixel_8t_intrin_avx2.c @@ -41,10 +41,7 @@ DECLARE_ALIGNED(32, static const uint8_t, filt4_global_avx2[32]) = { #if defined(__clang__) # if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ <= 3) || \ - (defined(__APPLE__) && \ - (__clang_major__ == 4 && __clang_minor__ >= 0 && \ - __clang_minor__ <= 2) || \ - (__clang_major__ == 5 && __clang_minor__ == 0)) + (defined(__APPLE__) && __clang_major__ == 5 && __clang_minor__ == 0) # define MM256_BROADCASTSI128_SI256(x) \ _mm_broadcastsi128_si256((__m128i const *)&(x)) # else // clang > 3.3, and not 5.0 on macosx. diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index 76b7dbc33f..1a6e529aa2 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -185,6 +185,7 @@ nsHttpConnectionMgr::Shutdown() // wait for shutdown event to complete while (!shutdownWrapper->mBool) { + fprintf(stderr, "nsHttpConnectionMgr::Shutdown() ProcessNextEvent\n"); NS_ProcessNextEvent(NS_GetCurrentThread()); } diff --git a/security/manager/ssl/nsIX509Cert.idl b/security/manager/ssl/nsIX509Cert.idl index d9ab1e33dd..396654956a 100644 --- a/security/manager/ssl/nsIX509Cert.idl +++ b/security/manager/ssl/nsIX509Cert.idl @@ -19,6 +19,11 @@ interface nsICertVerificationListener; /** * This represents a X.509 certificate. + * + * NOTE: Service workers persist x.509 certs in object form on disk. If you + * change this uuid you probably need a hack in nsBinaryInputStream to + * read the old uuid. If you change the format of the object + * serialization then more complex changes will be needed. */ [scriptable, uuid(bdc3979a-5422-4cd5-8589-696b6e96ea83)] interface nsIX509Cert : nsISupports { diff --git a/security/manager/ssl/tests/gtest/DeserializeCertTest.cpp b/security/manager/ssl/tests/gtest/DeserializeCertTest.cpp new file mode 100644 index 0000000000..e1a46283e7 --- /dev/null +++ b/security/manager/ssl/tests/gtest/DeserializeCertTest.cpp @@ -0,0 +1,96 @@ +/* -*- 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/. */ + +#include "gtest/gtest.h" +#include "nsCOMPtr.h" +#include "nsString.h" +#include "nsSerializationHelper.h" + +// These tests verify that we can still deserialize old binary strings +// generated for security info. This is necessary because service workers +// stores these strings on disk. +// +// If you make a change and start breaking these tests, you will need to +// add a compat fix for loading the old versions. For things that affect +// the UUID, but do not break the rest of the format you can simply add +// another hack condition in nsBinaryInputStream::ReadObject(). If you +// change the overall format of the serialization then we will need more +// complex handling in the security info concrete classes. +// +// We would like to move away from this binary compatibility requirement +// in service workers. See bug 1248628. + +TEST(DeserializeCert, gecko33) +{ + // Gecko 33+ vintage Security info serialized with UUIDs: + // - nsISupports 00000000-0000-0000-c000-000000000046 + // - nsISSLStatus fa9ba95b-ca3b-498a-b889-7c79cf28fee8 + // - nsIX509Cert f8ed8364-ced9-4c6e-86ba-48af53c393e6 + nsCString base64Serialization( + "FnhllAKWRHGAlo+ESXykKAAAAAAAAAAAwAAAAAAAAEaphjojH6pBabDSgSnsfLHeAAQAAgAAAAAAAAAAAAAAAAAAAAA" + "B4vFIJp5wRkeyPxAQ9RJGKPqbqVvKO0mKuIl8ec8o/uhmCjImkVxP+7sgiYWmMt8F+O2DZM7ZTG6GukivU8OT5gAAAAIAAAWpMII" + "FpTCCBI2gAwIBAgIQD4svsaKEC+QtqtsU2TF8ITANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUN" + "lcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFN" + "lcnZlciBDQTAeFw0xNTAyMjMwMDAwMDBaFw0xNjAzMDIxMjAwMDBaMGoxCzAJBgNVBAYTAlVTMRYwFAYDVQQHEw1TYW4gRnJhbmN" + "pc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRUwEwYDVQQKEwxGYXN0bHksIEluYy4xFzAVBgNVBAMTDnd3dy5naXRodWIuY29tMII" + "BIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+9WUCgrgUNwP/JC3cUefLAXeDpq8Ko/U8p8IRvny0Ri0I6Uq0t+RP/nF0LJ" + "Avda8QHYujdgeDTePepBX7+OiwBFhA0YO+rM3C2Z8IRaN/i9eLln+Yyc68+1z+E10s1EXdZrtDGvN6MHqygGsdfkXKfBLUJ1BZEh" + "s9sBnfcjq3kh5gZdBArdG9l5NpdmQhtceaFGsPiWuJxGxRzS4i95veUHWkhMpEYDEEBdcDGxqArvQCvzSlngdttQCfx8OUkBTb3B" + "A2okpTwwJfqPsxVetA6qR7UNc+fVb6KHwvm0bzi2rQ3xw3D/syRHwdMkpoVDQPCk43H9WufgfBKRen87dFwIDAQABo4ICPzCCAjs" + "wHwYDVR0jBBgwFoAUUWj/kK8CB3U8zNllZGKiErhZcjswHQYDVR0OBBYEFGS/RLNGCZvPWh1xSaIEcouINIQjMHsGA1UdEQR0MHK" + "CDnd3dy5naXRodWIuY29tggpnaXRodWIuY29tggwqLmdpdGh1Yi5jb22CCyouZ2l0aHViLmlvgglnaXRodWIuaW+CFyouZ2l0aHV" + "idXNlcmNvbnRlbnQuY29tghVnaXRodWJ1c2VyY29udGVudC5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwM" + "BBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzMuY3J" + "sMDSgMqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzMuY3JsMEIGA1UdIAQ7MDkwNwYJYIZIAYb" + "9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEFBQc" + "wAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUN" + "lcnRTSEEySGlnaEFzc3VyYW5jZVNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAc4dbVmuKvyI7" + "KZ4Txk+ZqcAYToJGKUIVaPL94e5SZGweUisjaCbplAOihnf6Mxt8n6vnuH2IsCaz2NRHqhdcosjT3CwAiJpJNkXPKWVL/txgdSTV" + "2cqB1GG4esFOalvI52dzn+J4fTIYZvNF+AtGyHSLm2XRXYZCw455laUKf6Sk9RDShDgUvzhOKL4GXfTwKXv12MyMknJybH8UCpjC" + "HZmFBVHMcUN/87HsQo20PdOekeEvkjrrMIxW+gxw22Yb67yF/qKgwrWr+43bLN709iyw+LWiU7sQcHL2xk9SYiWQDj2tYz2soObV" + "QYTJm0VUZMEVFhtALq46cx92Zu4vFwC8AAwAAAAABAQAA"); + + nsCOMPtr cert; + nsresult rv = NS_DeserializeObject(base64Serialization, getter_AddRefs(cert)); + ASSERT_EQ(NS_OK, rv); + ASSERT_TRUE(cert); +} + +TEST(DeserializeCert, gecko46) +{ + // Gecko 46+ vintage Security info serialized with UUIDs: + // - nsISupports 00000000-0000-0000-c000-000000000046 + // - nsISSLStatus fa9ba95b-ca3b-498a-b889-7c79cf28fee8 + // - nsIX509Cert bdc3979a-5422-4cd5-8589-696b6e96ea83 + nsCString base64Serialization( + "FnhllAKWRHGAlo+ESXykKAAAAAAAAAAAwAAAAAAAAEaphjojH6pBabDSgSnsfLHeAAQAAgAAAAAAAAAAAAAAAAAAAAA" + "B4vFIJp5wRkeyPxAQ9RJGKPqbqVvKO0mKuIl8ec8o/uhmCjImkVxP+7sgiYWmMt8FvcOXmlQiTNWFiWlrbpbqgwAAAAIAAAWzMII" + "FrzCCBJegAwIBAgIQB3pdwzYjAfmJ/lT3+G8+ZDANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUN" + "lcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFN" + "lcnZlciBDQTAeFw0xNjAxMjAwMDAwMDBaFw0xNzA0MDYxMjAwMDBaMGoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybml" + "hMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxGYXN0bHksIEluYy4xFzAVBgNVBAMTDnd3dy5naXRodWIuY29tMII" + "BIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+9WUCgrgUNwP/JC3cUefLAXeDpq8Ko/U8p8IRvny0Ri0I6Uq0t+RP/nF0LJ" + "Avda8QHYujdgeDTePepBX7+OiwBFhA0YO+rM3C2Z8IRaN/i9eLln+Yyc68+1z+E10s1EXdZrtDGvN6MHqygGsdfkXKfBLUJ1BZEh" + "s9sBnfcjq3kh5gZdBArdG9l5NpdmQhtceaFGsPiWuJxGxRzS4i95veUHWkhMpEYDEEBdcDGxqArvQCvzSlngdttQCfx8OUkBTb3B" + "A2okpTwwJfqPsxVetA6qR7UNc+fVb6KHwvm0bzi2rQ3xw3D/syRHwdMkpoVDQPCk43H9WufgfBKRen87dFwIDAQABo4ICSTCCAkU" + "wHwYDVR0jBBgwFoAUUWj/kK8CB3U8zNllZGKiErhZcjswHQYDVR0OBBYEFGS/RLNGCZvPWh1xSaIEcouINIQjMHsGA1UdEQR0MHK" + "CDnd3dy5naXRodWIuY29tggwqLmdpdGh1Yi5jb22CCmdpdGh1Yi5jb22CCyouZ2l0aHViLmlvgglnaXRodWIuaW+CFyouZ2l0aHV" + "idXNlcmNvbnRlbnQuY29tghVnaXRodWJ1c2VyY29udGVudC5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwM" + "BBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzUuY3J" + "sMDSgMqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzUuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb" + "9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMIGDBggrBgEFBQcBAQR3MHU" + "wJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggrBgEFBQcwAoZBaHR0cDovL2NhY2VydHMuZGlnaWNlcnQ" + "uY29tL0RpZ2lDZXJ0U0hBMkhpZ2hBc3N1cmFuY2VTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQE" + "ATxbRdPg+o49+96/P+rbdp4ie+CGtfCgUubT/Z9C54k+BfQO0nbxVgCSM5WZQuLgo2Q+0lcxisod8zxZeU0j5wviQINwOln/iN89" + "Bx3VmDRynTe4CqhsAwOoO1ERmCAmsAJBwY/rNr4mK22p8erBrqMW0nYXYU5NFynI+pNTjojhKD4II8PNV8G2yMWwYOb/u4+WPzUA" + "HC9DpZdrWTEH/W69Cr/KxRqGsWPwpgMv2Wqav8jaT35JxqTXjOlhQqzo6fNn3eYOeCf4PkCxZKwckWjy10qDaRbjhwAMHAGj2TPr" + "idlvOj/7QyyX5m8up/1US8z1fRW4yoCSOt6V2bwuH6cAvAAMAAAAAAQEAAA=="); + + nsCOMPtr cert; + nsresult rv = NS_DeserializeObject(base64Serialization, getter_AddRefs(cert)); + ASSERT_EQ(NS_OK, rv); + ASSERT_TRUE(cert); +} diff --git a/security/manager/ssl/tests/gtest/moz.build b/security/manager/ssl/tests/gtest/moz.build index eca30705b4..63315d715b 100644 --- a/security/manager/ssl/tests/gtest/moz.build +++ b/security/manager/ssl/tests/gtest/moz.build @@ -6,6 +6,7 @@ SOURCES += [ 'DataStorageTest.cpp', + 'DeserializeCertTest.cpp', 'OCSPCacheTest.cpp', 'TLSIntoleranceTest.cpp', ] diff --git a/toolkit/commonjs/sdk/system/environment.js b/toolkit/commonjs/sdk/system/environment.js index 04ae02cd85..13621a6969 100644 --- a/toolkit/commonjs/sdk/system/environment.js +++ b/toolkit/commonjs/sdk/system/environment.js @@ -12,53 +12,22 @@ const { Cc, Ci } = require('chrome'); const { get, set, exists } = Cc['@mozilla.org/process/environment;1']. getService(Ci.nsIEnvironment); -exports.env = Proxy.create({ - // XPCOM does not provides a way to enumerate environment variables, so we - // just don't support enumeration. - getPropertyNames: () => [], - getOwnPropertyNames: () => [], - enumerate: () => [], - keys: () => [], - // We do not support freezing, cause it would make it impossible to set new - // environment variables. - fix: () => undefined, - // We present all environment variables as own properties of this object, - // so we just delegate this call to `getOwnPropertyDescriptor`. - getPropertyDescriptor: function(name) { - return this.getOwnPropertyDescriptor(name); - }, - // If environment variable with this name is defined, we generate proprety - // descriptor for it, otherwise fall back to `undefined` so that for consumer - // this property does not exists. - getOwnPropertyDescriptor: function(name) { - return !exists(name) ? undefined : { - value: get(name), - enumerable: false, // Non-enumerable as we don't support enumeration. - configurable: true, // Configurable as it may be deleted. - writable: true // Writable as we do support set. - } - }, - - // New environment variables can be defined just by defining properties - // on this object. - defineProperty: (name, { value }) => set(name, value), - delete: function(name) { - set(name, null); +exports.env = new Proxy({}, { + deleteProperty(target, property) { + set(property, null); return true; }, - // We present all properties as own, there for we just delegate to `hasOwn`. - has: function(name) { - return this.hasOwn(name); + get(target, property, receiver) { + return get(property) || undefined; }, - // We do support checks for existence of an environment variable, via `in` - // operator on this object. - hasOwn: name => exists(name), - // On property get / set we do read / write appropriate environment variables, - // please note though, that variables with names of standard object properties - // intentionally (so that this behaves as normal object) can not be - // read / set. - get: (proxy, name) => Object.prototype[name] || get(name) || undefined, - set: (proxy, name, value) => Object.prototype[name] || set(name, value) + has(target, property) { + return exists(property); + }, + + set(target, property, value, receiver) { + set(property, value); + return true; + } }); diff --git a/toolkit/components/asyncshutdown/AsyncShutdown.jsm b/toolkit/components/asyncshutdown/AsyncShutdown.jsm index 50a775f567..a930090a4d 100644 --- a/toolkit/components/asyncshutdown/AsyncShutdown.jsm +++ b/toolkit/components/asyncshutdown/AsyncShutdown.jsm @@ -194,12 +194,16 @@ PromiseSet.prototype = { * console. We therefore use dump() rather than Cu.reportError(). */ function log(msg, prefix = "", error = null) { - dump(prefix + msg + "\n"); - if (error) { - dump(prefix + error + "\n"); - if (typeof error == "object" && "stack" in error) { - dump(prefix + error.stack + "\n"); + try { + dump(prefix + msg + "\n"); + if (error) { + dump(prefix + error + "\n"); + if (typeof error == "object" && "stack" in error) { + dump(prefix + error.stack + "\n"); + } } + } catch (ex) { + dump("INTERNAL ERROR in AsyncShutdown: cannot log message.\n"); } } const PREF_DEBUG_LOG = "toolkit.asyncshutdown.log"; @@ -305,35 +309,43 @@ function looseTimer(delay) { * @return object */ function getOrigin(topFrame, filename = null, lineNumber = null, stack = null) { - // Determine the filename and line number of the caller. - let frame = topFrame; + try { + // Determine the filename and line number of the caller. + let frame = topFrame; - for (; frame && frame.filename == topFrame.filename; frame = frame.caller) { - // Climb up the stack - } - - if (filename == null) { - filename = frame ? frame.filename : "?"; - } - if (lineNumber == null) { - lineNumber = frame ? frame.lineNumber : 0; - } - if (stack == null) { - // Now build the rest of the stack as a string, using Task.jsm's rewriting - // to ensure that we do not lose information at each call to `Task.spawn`. - let frames = []; - while (frame != null) { - frames.push(frame.filename + ":" + frame.name + ":" + frame.lineNumber); - frame = frame.caller; + for (; frame && frame.filename == topFrame.filename; frame = frame.caller) { + // Climb up the stack } - stack = Task.Debugging.generateReadableStack(frames.join("\n")).split("\n"); - } - return { - filename: filename, - lineNumber: lineNumber, - stack: stack, - }; + if (filename == null) { + filename = frame ? frame.filename : "?"; + } + if (lineNumber == null) { + lineNumber = frame ? frame.lineNumber : 0; + } + if (stack == null) { + // Now build the rest of the stack as a string, using Task.jsm's rewriting + // to ensure that we do not lose information at each call to `Task.spawn`. + let frames = []; + while (frame != null) { + frames.push(frame.filename + ":" + frame.name + ":" + frame.lineNumber); + frame = frame.caller; + } + stack = Task.Debugging.generateReadableStack(frames.join("\n")).split("\n"); + } + + return { + filename: filename, + lineNumber: lineNumber, + stack: stack, + }; + } catch (ex) { + return { + filename: "", + lineNumber: -1, + stack: "", + } + } } this.EXPORTED_SYMBOLS = ["AsyncShutdown"]; @@ -512,16 +524,26 @@ Spinner.prototype = { // nsIObserver.observe observe: function() { let topic = this._topic; + debug(`Starting phase ${ topic }`); let barrier = this._barrier; Services.obs.removeObserver(this, topic); let satisfied = false; // |true| once we have satisfied all conditions - let promise = this._barrier.wait({ - warnAfterMS: DELAY_WARNING_MS, - crashAfterMS: DELAY_CRASH_MS - }); + let promise; + try { + promise = this._barrier.wait({ + warnAfterMS: DELAY_WARNING_MS, + crashAfterMS: DELAY_CRASH_MS + }).catch( + // Additional precaution to be entirely sure that we cannot reject. + ); + } catch (ex) { + debug("Error waiting for notification"); + throw ex; + } // Now, spin the event loop + debug("Spinning the event loop"); promise.then(() => satisfied = true); // This promise cannot reject let thread = Services.tm.mainThread; while (!satisfied) { @@ -597,6 +619,9 @@ function Barrier(name) { /** * The name of the barrier. */ + if (typeof name != "string") { + throw new TypeError("The name of the barrier must be a string"); + } this._name = name; /** @@ -665,13 +690,16 @@ function Barrier(name) { throw new TypeError("Expected an object as third argument to `addBlocker`, got " + details); } if (!this._waitForMe) { - throw new Error(`Phase "${ this._name } is finished, it is too late to register completion condition "${ name }"`); + throw new Error(`Phase "${ this._name }" is finished, it is too late to register completion condition "${ name }"`); } debug(`Adding blocker ${ name } for phase ${ this._name }`); // Normalize the details let fetchState = details.fetchState || null; + if (fetchState != null && typeof fetchState != "function") { + throw new TypeError("Expected a function for option `fetchState`"); + } let filename = details.filename || null; let lineNumber = details.lineNumber || null; let stack = details.stack || null; @@ -713,7 +741,10 @@ function Barrier(name) { // The error should remain uncaught, to ensure that it // still causes tests to fail. Promise.reject(error); - }); + }).catch( + // Added as a last line of defense, in case `warn`, `this._name` or + // `safeGetState` somehow throws an error. + ); let topFrame = null; if (filename == null || lineNumber == null || stack == null) { diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc index d915fca640..2ccea4db24 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc +++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc @@ -532,7 +532,8 @@ bool ExceptionHandler::GenerateDump(CrashContext *context) { } if (child != 0) { - char *clonedMsg = "ExceptionHandler::GenerateDump cloned child "; + static const char clonedMsg[] = + "ExceptionHandler::GenerateDump cloned child "; char pidMsg[32]; unsigned int pidLen = my_uint_len(child); @@ -542,7 +543,8 @@ bool ExceptionHandler::GenerateDump(CrashContext *context) { logger::write(pidMsg, pidLen); logger::write("\n", 1); } else { - char *childMsg = "ExceptionHandler::GenerateDump I'm the child\n"; + static const char childMsg[] = + "ExceptionHandler::GenerateDump I'm the child\n"; logger::write(childMsg, my_strlen(childMsg)); } diff --git a/toolkit/crashreporter/test/CrashTestUtils.jsm b/toolkit/crashreporter/test/CrashTestUtils.jsm index 3a990ca111..7d33c2bb03 100644 --- a/toolkit/crashreporter/test/CrashTestUtils.jsm +++ b/toolkit/crashreporter/test/CrashTestUtils.jsm @@ -30,6 +30,7 @@ Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/ctypes.jsm"); var dir = Services.dirsvc.get("CurWorkD", Components.interfaces.nsILocalFile); var file = dir.clone(); +file = file.parent; file.append(ctypes.libraryName("testcrasher")); var lib = ctypes.open(file.path); CrashTestUtils.crash = lib.declare("Crash", diff --git a/toolkit/devtools/gcli/source/lib/gcli/util/l10n.js b/toolkit/devtools/gcli/source/lib/gcli/util/l10n.js index 15c5bc8f00..66fd2a45ac 100644 --- a/toolkit/devtools/gcli/source/lib/gcli/util/l10n.js +++ b/toolkit/devtools/gcli/source/lib/gcli/util/l10n.js @@ -71,7 +71,7 @@ exports.lookup = function(key) { }; /** @see propertyLookup in lib/gcli/util/l10n.js */ -exports.propertyLookup = Proxy.create({ +exports.propertyLookup = new Proxy({}, { get: function(rcvr, name) { return exports.lookup(name); } diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index 855b8fcaa4..b23c66cff4 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -650,53 +650,6 @@ var AddonManagerInternal = { // Store telemetry details per addon provider telemetryDetails: {}, - // A read-only wrapper around the types dictionary - typesProxy: Proxy.create({ - getOwnPropertyDescriptor: function typesProxy_getOwnPropertyDescriptor(aName) { - if (!(aName in AddonManagerInternal.types)) - return undefined; - - return { - value: AddonManagerInternal.types[aName].type, - writable: false, - configurable: false, - enumerable: true - } - }, - - getPropertyDescriptor: function typesProxy_getPropertyDescriptor(aName) { - return this.getOwnPropertyDescriptor(aName); - }, - - getOwnPropertyNames: function typesProxy_getOwnPropertyNames() { - return Object.keys(AddonManagerInternal.types); - }, - - getPropertyNames: function typesProxy_getPropertyNames() { - return this.getOwnPropertyNames(); - }, - - delete: function typesProxy_delete(aName) { - // Not allowed to delete properties - return false; - }, - - defineProperty: function typesProxy_defineProperty(aName, aProperty) { - // Ignore attempts to define properties - }, - - fix: function typesProxy_fix(){ - return undefined; - }, - - // Despite MDC's claims to the contrary, it is required that this trap - // be defined - enumerate: function typesProxy_enumerate() { - // All properties are enumerable - return this.getPropertyNames(); - } - }), - recordTimestamp: function AMI_recordTimestamp(name, value) { this.TelemetryTimestamps.add(name, value); }, @@ -2458,7 +2411,53 @@ var AddonManagerInternal = { }, get addonTypes() { - return this.typesProxy; + // A read-only wrapper around the types dictionary + return new Proxy(this.types, { + defineProperty(target, property, descriptor) { + // Not allowed to define properties + return false; + }, + + deleteProperty(target, property) { + // Not allowed to delete properties + return false; + }, + + get(target, property, receiver) { + if (!target.hasOwnProperty(property)) + return undefined; + + return target[property].type; + }, + + getOwnPropertyDescriptor(target, property) { + if (!target.hasOwnProperty(property)) + return undefined; + + return { + value: target[property].type, + writable: false, + // Claim configurability to maintain the proxy invariants. + configurable: true, + enumerable: true + } + }, + + preventExtensions(target) { + // Not allowed to prevent adding new properties + return false; + }, + + set(target, property, value, receiver) { + // Not allowed to set properties + return false; + }, + + setPrototypeOf(target, prototype) { + // Not allowed to change prototype + return false; + } + }); }, get autoUpdateDefault() { diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp index 6db9fb7fa2..1b1e4b3cae 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -396,6 +396,14 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent, bool unused; rv = dirsvc->GetFile("XCurProcD", &unused, getter_AddRefs(file)); } +#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) + else if (!strcmp(aProperty, NS_APP_CONTENT_PROCESS_TEMP_DIR)) { + if (!mContentTempDir && NS_FAILED((rv = LoadContentProcessTempDir()))) { + return rv; + } + rv = mContentTempDir->Clone(getter_AddRefs(file)); + } +#endif // defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX) else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) { // We need to allow component, xpt, and chrome registration to // occur prior to the profile-after-change notification. @@ -621,6 +629,50 @@ LoadExtensionDirectories(nsINIParser &parser, while (true); } +#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) + +static const char* +GetContentProcessTempBaseDirKey() +{ +#if defined(XP_WIN) + return NS_WIN_LOW_INTEGRITY_TEMP_BASE; +#else + return NS_OS_TEMP_DIR; +#endif +} + +nsresult +nsXREDirProvider::LoadContentProcessTempDir() +{ + nsCOMPtr localFile; + + nsresult rv = NS_GetSpecialDirectory(GetContentProcessTempBaseDirKey(), + getter_AddRefs(localFile)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsAutoString tempDirSuffix; + rv = Preferences::GetString("security.sandbox.content.tempDirSuffix", + &tempDirSuffix); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + if (tempDirSuffix.IsEmpty()) { + return NS_ERROR_NOT_AVAILABLE; + } + + rv = localFile->Append(NS_LITERAL_STRING("Temp-") + tempDirSuffix); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + localFile.swap(mContentTempDir); + return NS_OK; +} + +#endif // defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX) + void nsXREDirProvider::LoadExtensionBundleDirectories() { @@ -861,6 +913,7 @@ nsXREDirProvider::DoStartup() static const char16_t kStartup[] = {'s','t','a','r','t','u','p','\0'}; obsSvc->NotifyObservers(nullptr, "profile-do-change", kStartup); + // Init the Extension Manager nsCOMPtr em = do_GetService("@mozilla.org/addons/integration;1"); if (em) { diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h index eb27ed27fc..7c5263725d 100644 --- a/toolkit/xre/nsXREDirProvider.h +++ b/toolkit/xre/nsXREDirProvider.h @@ -124,6 +124,11 @@ protected: // delimiters. static inline nsresult AppendProfileString(nsIFile* aFile, const char* aPath); +#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) + // Load the temp directory for sandboxed content processes + nsresult LoadContentProcessTempDir(); +#endif + // Calculate and register extension and theme bundle directories. void LoadExtensionBundleDirectories(); @@ -144,6 +149,9 @@ protected: nsCOMPtr mProfileDir; nsCOMPtr mProfileLocalDir; bool mProfileNotified; +#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) + nsCOMPtr mContentTempDir; +#endif nsCOMArray mAppBundleDirectories; nsCOMArray mExtensionDirectories; nsCOMArray mThemeDirectories; diff --git a/tools/profiler/core/GeckoSampler.cpp b/tools/profiler/core/GeckoSampler.cpp index 7959de3c44..24690457d2 100644 --- a/tools/profiler/core/GeckoSampler.cpp +++ b/tools/profiler/core/GeckoSampler.cpp @@ -515,6 +515,7 @@ void GeckoSampler::StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime) if (TaskTracer()) { aWriter.StartObjectProperty("tasktracer"); StreamTaskTracer(aWriter); + aWriter.EndObject(); } // Lists the samples for each ThreadProfile @@ -951,7 +952,9 @@ void GeckoSampler::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSampl StackWalkCallback(/* frameNumber */ 0, aSample->pc, aSample->sp, &nativeStack); uint32_t maxFrames = uint32_t(nativeStack.size - nativeStack.count); -#if defined(XP_MACOSX) || defined(XP_WIN) + // win X64 doesn't support disabling frame pointers emission so we need + // to fallback to using StackWalk64 which is slower. +#if defined(XP_MACOSX) || (defined(XP_WIN) && !defined(V8_HOST_ARCH_X64)) void *stackEnd = aSample->threadProfile->GetStackTop(); bool rv = true; if (aSample->fp >= aSample->sp && aSample->fp <= stackEnd) diff --git a/tools/profiler/core/shared-libraries-linux.cc b/tools/profiler/core/shared-libraries-linux.cc index 3b67d3b2c9..e9740783ac 100644 --- a/tools/profiler/core/shared-libraries-linux.cc +++ b/tools/profiler/core/shared-libraries-linux.cc @@ -63,7 +63,8 @@ int dl_iterate_phdr( void *data); #endif -int dl_iterate_callback(struct dl_phdr_info *dl_info, size_t size, void *data) +static int +dl_iterate_callback(struct dl_phdr_info *dl_info, size_t size, void *data) { SharedLibraryInfo& info = *reinterpret_cast(data); @@ -90,7 +91,8 @@ int dl_iterate_callback(struct dl_phdr_info *dl_info, size_t size, void *data) return 0; } -#endif + +#endif // !MOZ_WIDGET_GONK SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() { @@ -105,13 +107,12 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() // not call it. return info; } -#endif - dl_iterate_phdr(dl_iterate_callback, &info); -#ifndef ANDROID - return info; -#endif -#endif +#endif // ANDROID + dl_iterate_phdr(dl_iterate_callback, &info); +#endif // !MOZ_WIDGET_GONK + +#if defined(ANDROID) || defined(MOZ_WIDGET_GONK) pid_t pid = getpid(); char path[PATH_MAX]; snprintf(path, PATH_MAX, "/proc/%d/maps", pid); @@ -158,5 +159,7 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() } count++; } +#endif // ANDROID || MOZ_WIDGET_GONK + return info; } diff --git a/tools/profiler/public/GeckoProfiler.h b/tools/profiler/public/GeckoProfiler.h index acb7e2029b..15d53ad852 100644 --- a/tools/profiler/public/GeckoProfiler.h +++ b/tools/profiler/public/GeckoProfiler.h @@ -77,7 +77,7 @@ enum TracingMetadata { TRACING_TIMESTAMP }; -#if !defined(MOZ_ENABLE_PROFILER_SPS) || defined(MOZILLA_XPCOMRT_API) +#if !defined(MOZ_ENABLE_PROFILER_SPS) #include #include diff --git a/tools/profiler/public/GeckoProfilerFunc.h b/tools/profiler/public/GeckoProfilerFunc.h index e0a7bd6082..bc9562a365 100644 --- a/tools/profiler/public/GeckoProfilerFunc.h +++ b/tools/profiler/public/GeckoProfilerFunc.h @@ -30,21 +30,37 @@ class ProfilerMarkerPayload; // Returns a handle to pass on exit. This can check that we are popping the // correct callstack. -inline void* mozilla_sampler_call_enter(const char *aInfo, void *aFrameAddress = NULL, bool aCopy = false, uint32_t line = 0); +inline void* mozilla_sampler_call_enter(const char *aInfo, js::ProfileEntry::Category aCategory, + void *aFrameAddress = nullptr, bool aCopy = false, + uint32_t line = 0); inline void mozilla_sampler_call_exit(void* handle); void mozilla_sampler_add_marker(const char *aInfo, ProfilerMarkerPayload *aPayload = nullptr); -void mozilla_sampler_start(int aEntries, int aInterval, const char** aFeatures, uint32_t aFeatureCount); +void mozilla_sampler_start(int aEntries, double aInterval, + const char** aFeatures, uint32_t aFeatureCount, + const char** aThreadNameFilters, uint32_t aFilterCount); + void mozilla_sampler_stop(); +bool mozilla_sampler_is_paused(); +void mozilla_sampler_pause(); +void mozilla_sampler_resume(); + +ProfilerBacktrace* mozilla_sampler_get_backtrace(); +void mozilla_sampler_free_backtrace(ProfilerBacktrace* aBacktrace); void mozilla_sampler_get_backtrace_noalloc(char *output, size_t outputSize); bool mozilla_sampler_is_active(); -void mozilla_sampler_responsiveness(TimeStamp time); + +bool mozilla_sampler_feature_active(const char* aName); + +void mozilla_sampler_responsiveness(const mozilla::TimeStamp& time); + void mozilla_sampler_frame_number(int frameNumber); + const double* mozilla_sampler_get_responsiveness(); void mozilla_sampler_save(); @@ -73,9 +89,9 @@ const char** mozilla_sampler_get_features(); void mozilla_sampler_get_buffer_info(uint32_t *aCurrentPosition, uint32_t *aTotalSize, uint32_t *aGeneration); -void mozilla_sampler_init(); +void mozilla_sampler_init(void* stackTop); + void mozilla_sampler_shutdown(); -void mozilla_sampler_print_location(); // Lock the profiler. When locked the profiler is (1) stopped, // (2) profile data is cleared, (3) profiler-locked is fired. @@ -95,5 +111,14 @@ void mozilla_sampler_sleep_end(); double mozilla_sampler_time(); double mozilla_sampler_time(const mozilla::TimeStamp& aTime); +void mozilla_sampler_tracing(const char* aCategory, const char* aInfo, + TracingMetadata aMetaData); + +void mozilla_sampler_tracing(const char* aCategory, const char* aInfo, + ProfilerBacktrace* aCause, + TracingMetadata aMetaData); + +void mozilla_sampler_log(const char *fmt, va_list args); + #endif diff --git a/tools/profiler/public/GeckoProfilerImpl.h b/tools/profiler/public/GeckoProfilerImpl.h index 2b565af15c..9016be9a92 100644 --- a/tools/profiler/public/GeckoProfilerImpl.h +++ b/tools/profiler/public/GeckoProfilerImpl.h @@ -411,23 +411,26 @@ protected: const char* mInfo; }; -class MOZ_STACK_CLASS SamplerStackFrameRAII { +class MOZ_RAII SamplerStackFrameRAII { public: // we only copy the strings at save time, so to take multiple parameters we'd need to copy them then. SamplerStackFrameRAII(const char *aInfo, - js::ProfileEntry::Category aCategory, uint32_t line) + js::ProfileEntry::Category aCategory, uint32_t line + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; mHandle = mozilla_sampler_call_enter(aInfo, aCategory, this, false, line); } ~SamplerStackFrameRAII() { mozilla_sampler_call_exit(mHandle); } private: + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER void* mHandle; }; static const int SAMPLER_MAX_STRING = 128; -class MOZ_STACK_CLASS SamplerStackFramePrintfRAII { +class MOZ_RAII SamplerStackFramePrintfRAII { public: // we only copy the strings at save time, so to take multiple parameters we'd need to copy them then. SamplerStackFramePrintfRAII(const char *aInfo, diff --git a/xpcom/base/nsAgg.h b/xpcom/base/nsAgg.h index aab49d805b..57038f856b 100644 --- a/xpcom/base/nsAgg.h +++ b/xpcom/base/nsAgg.h @@ -295,16 +295,13 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \ if (NS_WARN_IF(aOuter && !aIID.Equals(NS_GET_IID(nsISupports)))) \ return NS_ERROR_INVALID_ARG; \ \ - _InstanceClass* inst = new _InstanceClass(aOuter); \ + RefPtr<_InstanceClass> inst = new _InstanceClass(aOuter); \ if (!inst) { \ return NS_ERROR_OUT_OF_MEMORY; \ } \ \ nsISupports* inner = inst->InnerObject(); \ nsresult rv = inner->QueryInterface(aIID, aResult); \ - if (NS_FAILED(rv)) { \ - delete inst; \ - } \ \ return rv; \ } \ @@ -318,7 +315,7 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \ if (NS_WARN_IF(aOuter && !aIID.Equals(NS_GET_IID(nsISupports)))) \ return NS_ERROR_INVALID_ARG; \ \ - _InstanceClass* inst = new _InstanceClass(aOuter); \ + RefPtr<_InstanceClass> inst = new _InstanceClass(aOuter); \ if (!inst) { \ return NS_ERROR_OUT_OF_MEMORY; \ } \ diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index 8a3117bdf1..c00cec6c67 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -2461,8 +2461,9 @@ CCGraphBuilder::NoteWeakMapping(JSObject* aMap, JS::GCCellPtr aKey, mapping->mVal = aVal ? AddWeakMapNode(aVal) : nullptr; if (mLogger) { - mLogger->NoteWeakMapEntry((uint64_t)aMap, aKey.unsafeAsInteger(), - (uint64_t)aKdelegate, aVal.unsafeAsInteger()); + mLogger->NoteWeakMapEntry((uint64_t)aMap, aKey ? aKey.unsafeAsInteger() : 0, + (uint64_t)aKdelegate, + aVal ? aVal.unsafeAsInteger() : 0); } } @@ -3271,6 +3272,7 @@ nsCycleCollector::CollectWhite() PtrInfo* pinfo = etor.GetNext(); if (pinfo->mColor == white && pinfo->mParticipant) { if (pinfo->IsGrayJS()) { + MOZ_ASSERT(mJSRuntime); ++numWhiteGCed; JS::Zone* zone; if (MOZ_UNLIKELY(pinfo->mParticipant == zoneParticipant)) { diff --git a/xpcom/io/nsAppDirectoryServiceDefs.h b/xpcom/io/nsAppDirectoryServiceDefs.h index 38e02fab40..b80db172d1 100644 --- a/xpcom/io/nsAppDirectoryServiceDefs.h +++ b/xpcom/io/nsAppDirectoryServiceDefs.h @@ -89,4 +89,9 @@ #define NS_APP_INDEXEDDB_PARENT_DIR "indexedDBPDir" #define NS_APP_PERMISSION_PARENT_DIR "permissionDBPDir" -#endif + +#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) +#define NS_APP_CONTENT_PROCESS_TEMP_DIR "ContentTmpD" +#endif // (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) + +#endif // nsAppDirectoryServiceDefs_h___ diff --git a/xpcom/io/nsBinaryStream.cpp b/xpcom/io/nsBinaryStream.cpp index 9c11b3f6b3..ea6a5241e9 100644 --- a/xpcom/io/nsBinaryStream.cpp +++ b/xpcom/io/nsBinaryStream.cpp @@ -33,6 +33,7 @@ #include "nsIClassInfo.h" #include "nsComponentManagerUtils.h" #include "nsIURI.h" // for NS_IURI_IID +#include "nsIX509Cert.h" // for NS_IX509CERT_IID #include "jsfriendapi.h" @@ -934,6 +935,23 @@ nsBinaryInputStream::ReadObject(bool aIsStrongRef, nsISupports** aObject) } // END HACK + // HACK: Service workers store resource security info on disk in the dom + // Cache API. When the uuid of the nsIX509Cert interface changes + // these serialized objects cannot be loaded any more. This hack + // works around this issue. + + // hackaround for bug 1247580 (FF45 to FF46 transition) + static const nsIID oldCertIID = { + 0xf8ed8364, 0xced9, 0x4c6e, + { 0x86, 0xba, 0x48, 0xaf, 0x53, 0xc3, 0x93, 0xe6 } + }; + + if (iid.Equals(oldCertIID)) { + const nsIID newCertIID = NS_IX509CERT_IID; + iid = newCertIID; + } + // END HACK + nsCOMPtr object = do_CreateInstance(cid, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; diff --git a/xpcom/io/nsLocalFileWin.cpp b/xpcom/io/nsLocalFileWin.cpp index 2c03a814e4..e8b5c5be1d 100644 --- a/xpcom/io/nsLocalFileWin.cpp +++ b/xpcom/io/nsLocalFileWin.cpp @@ -481,6 +481,7 @@ ConvertWinError(DWORD aWinErr) case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: case ERROR_INVALID_DRIVE: + case ERROR_NOT_READY: rv = NS_ERROR_FILE_NOT_FOUND; break; case ERROR_ACCESS_DENIED: @@ -807,7 +808,6 @@ ReadDir(nsDir* aDir, PRDirFlags aFlags, nsString& aName) } const wchar_t* fileName; - nsString tmp; fileName = (aDir)->data.cFileName; if ((aFlags & PR_SKIP_DOT) && @@ -825,11 +825,7 @@ ReadDir(nsDir* aDir, PRDirFlags aFlags, nsString& aName) continue; } - if (fileName == tmp.get()) { - aName = tmp; - } else { - aName = fileName; - } + aName = fileName; return NS_OK; } diff --git a/xpcom/io/nsScriptableInputStream.cpp b/xpcom/io/nsScriptableInputStream.cpp index 1a4f884ccd..9a951714cc 100644 --- a/xpcom/io/nsScriptableInputStream.cpp +++ b/xpcom/io/nsScriptableInputStream.cpp @@ -81,11 +81,11 @@ nsScriptableInputStream::ReadBytes(uint32_t aCount, nsACString& aResult) return NS_ERROR_NOT_INITIALIZED; } - aResult.SetLength(aCount); - if (aResult.Length() != aCount) { + if (!aResult.SetLength(aCount, fallible)) { return NS_ERROR_OUT_OF_MEMORY; } + MOZ_ASSERT(aResult.Length() == aCount); char* ptr = aResult.BeginWriting(); nsresult rv = ReadHelper(ptr, aCount); if (NS_FAILED(rv)) { diff --git a/xpcom/moz.build b/xpcom/moz.build index 7d273c95e6..fdd2183b52 100644 --- a/xpcom/moz.build +++ b/xpcom/moz.build @@ -31,7 +31,6 @@ if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_DEBUG']: TEST_DIRS += [ 'tests', - 'typelib/xpt/tests', ] # Can't build internal xptcall tests that use symbols which are not exported. diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build index 8c37b308d3..d79e2ae73f 100644 --- a/xpcom/reflect/xptcall/md/unix/moz.build +++ b/xpcom/reflect/xptcall/md/unix/moz.build @@ -24,7 +24,7 @@ if CONFIG['OS_ARCH'] == 'GNU': 'xptcstubs_gcc_x86_unix.cpp' ] -if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD', 'OpenBSD') or \ +if CONFIG['OS_ARCH'] in ('Linux', 'Bitrig', 'DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD') or \ CONFIG['OS_ARCH'].startswith('GNU_'): if CONFIG['OS_TEST'] == 'x86_64': SOURCES += [ @@ -98,7 +98,7 @@ if CONFIG['CPU_ARCH'] == 'arm' or CONFIG['OS_TEST'] == 'sa110': 'xptcstubs_arm_netbsd.cpp', ] -if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['OS_ARCH'] == 'OpenBSD': +if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['OS_ARCH'] in ('Bitrig', 'OpenBSD'): SOURCES += [ 'xptcinvoke_arm_openbsd.cpp', 'xptcstubs_arm_openbsd.cpp', diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp index d64837a569..4cd5eb47d8 100644 --- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp @@ -113,6 +113,12 @@ invoke_copy_to_stack(uint32_t* stk, uint32_t *end, typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t); +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_BLACKLIST EXPORT_XPCOM_API(nsresult) NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, uint32_t paramCount, nsXPTCVariant* params) diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp index 9b688753e8..573dfb00c2 100644 --- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp @@ -170,6 +170,12 @@ invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d_ov, uint typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t, uint32_t, double, double); +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_BLACKLIST EXPORT_XPCOM_API(nsresult) NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, uint32_t paramCount, nsXPTCVariant* params) diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp index 86d800ec77..86478a8502 100644 --- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp @@ -164,6 +164,12 @@ invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint64_t* d_ov, uint typedef nsresult (*vtable_func)(nsISupports *, uint64_t, uint64_t, uint64_t, uint64_t, double, double, double, double); +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_BLACKLIST EXPORT_XPCOM_API(nsresult) NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, uint32_t paramCount, nsXPTCVariant* params) diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp index 4f63ea822f..0d34243663 100644 --- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp @@ -100,6 +100,12 @@ invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s, } } +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_BLACKLIST EXPORT_XPCOM_API(nsresult) NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex, uint32_t paramCount, nsXPTCVariant * params) diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp index f4853bee13..08e5198897 100644 --- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp @@ -47,9 +47,9 @@ static void invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s, uint64_t * gpregs, double * fpregs) { - uint32_t nr_gpr = 1; // skip one GP register for 'that' - uint32_t nr_fpr = 0; - uint64_t value; + uint32_t nr_gpr = 1u; // skip one GP register for 'that' + uint32_t nr_fpr = 0u; + uint64_t value = 0u; for (uint32_t i = 0; i < paramCount; i++, s++) { if (s->IsPtrData()) @@ -113,6 +113,12 @@ invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s, #pragma GCC target ("no-avx") #endif +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_BLACKLIST EXPORT_XPCOM_API(nsresult) NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex, uint32_t paramCount, nsXPTCVariant * params) diff --git a/xpcom/reflect/xptcall/md/win32/moz.build b/xpcom/reflect/xptcall/md/win32/moz.build index 46fc1aff01..eccf0e33dd 100644 --- a/xpcom/reflect/xptcall/md/win32/moz.build +++ b/xpcom/reflect/xptcall/md/win32/moz.build @@ -31,9 +31,11 @@ else: else: SOURCES += [ 'xptcinvoke.cpp', + 'xptcinvoke_asm_x86_msvc.asm', 'xptcstubs.cpp', ] SOURCES['xptcinvoke.cpp'].no_pgo = True + SOURCES['xptcinvoke_asm_x86_msvc.asm'].flags += ['-safeseh'] FINAL_LIBRARY = 'xul' diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp index a4019abd88..faec869f6d 100644 --- a/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp @@ -11,7 +11,7 @@ #error "This code is for Win32 only" #endif -static void __fastcall +extern "C" void __fastcall invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) { for(; paramCount > 0; paramCount--, d++, s++) @@ -43,40 +43,3 @@ invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) } } } - -#pragma warning(disable : 4035) // OK to have no return value -// Tell the PDB file this function has a standard frame pointer, and not to use -// a custom FPO program. -#pragma optimize( "y", off ) -extern "C" NS_EXPORT nsresult NS_FROZENCALL -NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, - uint32_t paramCount, nsXPTCVariant* params) -{ - __asm { - mov edx,paramCount // Save paramCount for later - test edx,edx // maybe we don't have any params to copy - jz noparams - mov eax,edx - shl eax,3 // *= 8 (max possible param size) - sub esp,eax // make space for params - mov ecx,esp - push params - call invoke_copy_to_stack // fastcall, ecx = d, edx = paramCount, params is on the stack -noparams: - mov ecx,that // instance in ecx - push ecx // push this - mov edx,[ecx] // vtable in edx - mov eax,methodIndex - call dword ptr[edx+eax*4] // stdcall, i.e. callee cleans up stack. - mov esp,ebp -#ifdef __clang__ - // clang-cl doesn't emit the pop and ret instructions because it doesn't realize - // that the call instruction sets a return value in eax. See - // https://bugzilla.mozilla.org/show_bug.cgi?id=1028613 and - // http://llvm.org/bugs/show_bug.cgi?id=17201. - pop ebp - ret -#endif - } -} -#pragma warning(default : 4035) // restore default diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm new file mode 100644 index 0000000000..f3b7a1826d --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm @@ -0,0 +1,63 @@ +; 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/. + + TITLE xptcinvoke_asm_x86_msvc.asm + .686P + .model flat + +PUBLIC _NS_InvokeByIndex +EXTRN @invoke_copy_to_stack@12:PROC + +; +; extern "C" nsresult __cdecl +; NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +; uint32_t paramCount, nsXPTCVariant* params) +; + +_TEXT SEGMENT +_NS_InvokeByIndex PROC + + ; Build frame + push ebp + mov ebp, esp + + ; Save paramCount for later + mov edx, dword ptr [ebp+16] + + ; Do we have any parameters? + test edx, edx + jz noparams + + ; Build call for copy_to_stack, which is __fastcall + + ; Allocate space for parameters. 8 is the biggest size + ; any parameter can be, so assume that all our parameters + ; are that large. + mov eax, edx + shl eax, 3 + sub esp, eax + + mov ecx, esp + push dword ptr [ebp+20] + call @invoke_copy_to_stack@12 +noparams: + ; Push the `this' parameter for the call. + mov ecx, dword ptr [ebp+8] + push ecx + + ; Load the vtable. + mov edx, dword ptr [ecx] + + ; Call the vtable index at `methodIndex'. + mov eax, dword ptr [ebp+12] + call dword ptr [edx+eax*4] + + ; Reset and return. + mov esp, ebp + pop ebp + ret +_NS_InvokeByIndex ENDP +_TEXT ENDS + +END diff --git a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp index a93d5b0b2e..868986c769 100644 --- a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp +++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sw=4 et tw=78: * * This Source Code Form is subject to the terms of the Mozilla Public @@ -278,9 +278,14 @@ using namespace mozilla; struct ComponentsInterfaceShimEntry { + MOZ_CONSTEXPR + ComponentsInterfaceShimEntry(const char* aName, const nsIID& aIID, + const dom::NativePropertyHooks* aNativePropHooks) + : geckoName(aName), iid(aIID), nativePropHooks(aNativePropHooks) {} + const char *geckoName; - nsIID iid; - const mozilla::dom::NativePropertyHooks* nativePropHooks; + const nsIID& iid; + const dom::NativePropertyHooks* nativePropHooks; }; #define DEFINE_SHIM_WITH_CUSTOM_INTERFACE(geckoName, domName) \ diff --git a/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp b/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp index c997cfc878..57587d4ebb 100644 --- a/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp +++ b/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp @@ -48,9 +48,10 @@ xptiInterfaceEntry::Create(const char* name, const nsID& iid, xptiTypelibGuts* aTypelib) { int namelen = strlen(name); - return new (XPT_MALLOC(gXPTIStructArena, - sizeof(xptiInterfaceEntry) + namelen)) - xptiInterfaceEntry(name, namelen, iid, aDescriptor, aTypelib); + void* place = + XPT_CALLOC8(gXPTIStructArena, sizeof(xptiInterfaceEntry) + namelen); + return new (place) xptiInterfaceEntry(name, namelen, iid, aDescriptor, + aTypelib); } xptiInterfaceEntry::xptiInterfaceEntry(const char* name, @@ -60,11 +61,11 @@ xptiInterfaceEntry::xptiInterfaceEntry(const char* name, xptiTypelibGuts* aTypelib) : mIID(iid) , mDescriptor(aDescriptor) - , mMethodBaseIndex(0) - , mConstantBaseIndex(0) , mTypelib(aTypelib) , mParent(nullptr) , mInfo(nullptr) + , mMethodBaseIndex(0) + , mConstantBaseIndex(0) , mFlags(0) { memcpy(mName, name, nameLength); @@ -343,7 +344,7 @@ xptiInterfaceEntry::GetInterfaceIndexForParam(uint16_t methodIndex, const XPTTypeDescriptor *td = ¶m->type; while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { - td = &mDescriptor->additional_types[td->type.additional_type]; + td = &mDescriptor->additional_types[td->u.array.additional_type]; } if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) { @@ -351,7 +352,7 @@ xptiInterfaceEntry::GetInterfaceIndexForParam(uint16_t methodIndex, return NS_ERROR_INVALID_ARG; } - *interfaceIndex = td->type.iface; + *interfaceIndex = (td->u.iface.iface_hi8 << 8) | td->u.iface.iface_lo8; return NS_OK; } @@ -482,7 +483,7 @@ xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param, NS_ERROR("bad dimension"); return NS_ERROR_INVALID_ARG; } - td = &additional_types[td->type.additional_type]; + td = &additional_types[td->u.array.additional_type]; } *type = td; @@ -556,15 +557,17 @@ xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16_t methodIndex, // verify that this is a type that has size_is switch (XPT_TDP_TAG(td->prefix)) { case TD_ARRAY: + *argnum = td->u.array.argnum; + break; case TD_PSTRING_SIZE_IS: case TD_PWSTRING_SIZE_IS: + *argnum = td->u.pstring_is.argnum; break; default: NS_ERROR("not a size_is"); return NS_ERROR_INVALID_ARG; } - *argnum = td->argnum; return NS_OK; } @@ -590,8 +593,7 @@ xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const XPTTypeDescriptor *td = ¶m->type; while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { - td = &mDescriptor-> - additional_types[td->type.additional_type]; + td = &mDescriptor->additional_types[td->u.array.additional_type]; } if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) { @@ -599,7 +601,7 @@ xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16_t methodIndex, return NS_ERROR_INVALID_ARG; } - *argnum = td->argnum; + *argnum = td->u.interface_is.argnum; return NS_OK; } diff --git a/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp b/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp index afc1656c20..9793ed4280 100644 --- a/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp +++ b/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp @@ -52,7 +52,7 @@ XPTInterfaceInfoManager::CollectReports(nsIHandleReportCallback* aHandleReport, // Measure gXPTIStructArena here, too. This is a bit grotty because it // doesn't belong to the XPTIInterfaceInfoManager, but there's no // obviously better place to measure it. - amount += XPT_SizeOfArena(gXPTIStructArena, XPTIMallocSizeOf); + amount += XPT_SizeOfArenaIncludingThis(gXPTIStructArena, XPTIMallocSizeOf); return MOZ_COLLECT_REPORT( "explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, amount, @@ -99,13 +99,11 @@ XPTInterfaceInfoManager::InitMemoryReporter() void XPTInterfaceInfoManager::RegisterBuffer(char *buf, uint32_t length) { - XPTState *state = XPT_NewXDRState(XPT_DECODE, buf, length); - if (!state) - return; + XPTState state; + XPT_InitXDRState(&state, buf, length); XPTCursor cursor; - if (!XPT_MakeCursor(state, XPT_HEADER, 0, &cursor)) { - XPT_DestroyXDRState(state); + if (!XPT_MakeCursor(&state, XPT_HEADER, 0, &cursor)) { return; } @@ -113,8 +111,6 @@ XPTInterfaceInfoManager::RegisterBuffer(char *buf, uint32_t length) if (XPT_DoHeader(gXPTIStructArena, &cursor, &header)) { RegisterXPTHeader(header); } - - XPT_DestroyXDRState(state); } void diff --git a/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp b/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp index 2661912ad1..8474a5331e 100644 --- a/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp +++ b/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp @@ -22,11 +22,10 @@ xptiTypelibGuts* xptiTypelibGuts::Create(XPTHeader* aHeader) { NS_ASSERTION(aHeader, "bad param"); - void* place = XPT_MALLOC(gXPTIStructArena, - sizeof(xptiTypelibGuts) + - (sizeof(xptiInterfaceEntry*) * - (aHeader->num_interfaces - 1))); - if(!place) + size_t n = sizeof(xptiTypelibGuts) + + sizeof(xptiInterfaceEntry*) * (aHeader->num_interfaces - 1); + void* place = XPT_CALLOC8(gXPTIStructArena, n); + if (!place) return nullptr; return new(place) xptiTypelibGuts(aHeader); } diff --git a/xpcom/reflect/xptinfo/xptiWorkingSet.cpp b/xpcom/reflect/xptinfo/xptiWorkingSet.cpp index cb9fe8774f..10f81a4b2b 100644 --- a/xpcom/reflect/xptinfo/xptiWorkingSet.cpp +++ b/xpcom/reflect/xptinfo/xptiWorkingSet.cpp @@ -13,8 +13,10 @@ using namespace mozilla; -#define XPTI_STRUCT_ARENA_BLOCK_SIZE (1024 * 16) -#define XPTI_HASHTABLE_LENGTH 1024 +static const size_t XPTI_ARENA8_BLOCK_SIZE = 16 * 1024; +static const size_t XPTI_ARENA1_BLOCK_SIZE = 8 * 1024; + +static const uint32_t XPTI_HASHTABLE_LENGTH = 1024; XPTInterfaceInfoManager::xptiWorkingSet::xptiWorkingSet() : mTableReentrantMonitor("xptiWorkingSet::mTableReentrantMonitor") @@ -23,8 +25,8 @@ XPTInterfaceInfoManager::xptiWorkingSet::xptiWorkingSet() { MOZ_COUNT_CTOR(xptiWorkingSet); - gXPTIStructArena = XPT_NewArena(XPTI_STRUCT_ARENA_BLOCK_SIZE, sizeof(double), - "xptiWorkingSet structs"); + gXPTIStructArena = XPT_NewArena(XPTI_ARENA8_BLOCK_SIZE, + XPTI_ARENA1_BLOCK_SIZE); } void diff --git a/xpcom/reflect/xptinfo/xptinfo.h b/xpcom/reflect/xptinfo/xptinfo.h index 5e1981607e..9ba105cc95 100644 --- a/xpcom/reflect/xptinfo/xptinfo.h +++ b/xpcom/reflect/xptinfo/xptinfo.h @@ -187,7 +187,6 @@ public: bool IsGetter() const {return 0 != (XPT_MD_IS_GETTER(flags) );} bool IsSetter() const {return 0 != (XPT_MD_IS_SETTER(flags) );} bool IsNotXPCOM() const {return 0 != (XPT_MD_IS_NOTXPCOM(flags));} - bool IsConstructor() const {return 0 != (XPT_MD_IS_CTOR(flags) );} bool IsHidden() const {return 0 != (XPT_MD_IS_HIDDEN(flags) );} bool WantsOptArgc() const {return 0 != (XPT_MD_WANTS_OPT_ARGC(flags));} bool WantsContext() const {return 0 != (XPT_MD_WANTS_CONTEXT(flags));} diff --git a/xpcom/reflect/xptinfo/xptiprivate.h b/xpcom/reflect/xptinfo/xptiprivate.h index 758801b705..5aa19f8d8d 100644 --- a/xpcom/reflect/xptinfo/xptiprivate.h +++ b/xpcom/reflect/xptinfo/xptiprivate.h @@ -307,8 +307,6 @@ private: nsID mIID; XPTInterfaceDescriptor* mDescriptor; - uint16_t mMethodBaseIndex; - uint16_t mConstantBaseIndex; xptiTypelibGuts* mTypelib; xptiInterfaceEntry* mParent; // Valid only when fully resolved @@ -316,7 +314,12 @@ private: xptiInterfaceInfo* MOZ_UNSAFE_REF("The safety of this pointer is ensured " "by the semantics of xptiWorkingSet.") mInfo; // May come and go. + + uint16_t mMethodBaseIndex; + uint16_t mConstantBaseIndex; + xptiInfoFlags mFlags; + char mName[1]; // Always last. Sized to fit. }; diff --git a/xpcom/typelib/xpt/tests/PrimitiveTest.cpp b/xpcom/typelib/xpt/tests/PrimitiveTest.cpp deleted file mode 100644 index cc1482652b..0000000000 --- a/xpcom/typelib/xpt/tests/PrimitiveTest.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -/* Test the xdr primitives from xpt_xdr.c */ - -#include "xpt_xdr.h" -#include -#include /* for memcpy */ - -#define PASS(msg) \ - fprintf(stderr, "PASSED : %s\n", msg); - -#define FAIL(msg) \ - fprintf(stderr, "FAILURE: %s\n", msg); - -#define TRY_(msg, cond, silent) \ - if ((cond) && !silent) { \ - PASS(msg); \ - } else { \ - FAIL(msg); \ - return 1; \ - } - -#define TRY(msg, cond) TRY_(msg, cond, 0) -#define TRY_Q(msg, cond) TRY_(msg, cond, 1); - -static char bazz[] = "bazz"; -XPTString in_str = { 4, bazz }; - -static char foobar[] = "foobar"; -struct TestData { - uint32_t bit32; - uint16_t bit16; - uint8_t bit8[2]; - char *cstr; - XPTString *str; -} input = { 0xdeadbeef, 0xcafe, {0xba, 0xbe}, foobar, &in_str}, - output = {0, 0, {0, 0}, NULL, NULL }; - -void -dump_struct(const char *label, struct TestData *str) -{ - fprintf(stderr, "%s: {%#08x, %#04x, {%#02x, %#02x}, %s, %d/%s}\n", - label, str->bit32, str->bit16, str->bit8[0], str->bit8[1], - str->cstr, str->str->length, str->str->bytes); -} - -PRBool -XDR(XPTArena *arena, XPTCursor *cursor, struct TestData *str) -{ - TRY("Do32", XPT_Do32(cursor, &str->bit32)); - TRY("Do16", XPT_Do16(cursor, &str->bit16)); - TRY("Do8", XPT_Do8 (cursor, &str->bit8[0])); - TRY("Do8", XPT_Do8 (cursor, &str->bit8[1])); - TRY("DoCString", XPT_DoCString(arena, cursor, &str->cstr)); - TRY("DoString", XPT_DoString(arena, cursor, &str->str)); - return 0; -} - -int -main(int argc, char **argv) -{ - XPTArena *arena; - XPTState *state; - XPTCursor curs, *cursor = &curs; - char *header, *data, *whole; - uint32_t hlen, dlen, i; - - TRY("XPT_NewArena", (arena = XPT_NewArena(1024, sizeof(double), "main"))); - - TRY("NewState (ENCODE)", (state = XPT_NewXDRState(XPT_ENCODE, NULL, 0))); - - XPT_SetDataOffset(state, sizeof input); - - TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor)); - - dump_struct("before", &input); - - if (XDR(arena, cursor, &input)) - return 1; - - fprintf(stderr, "ENCODE successful\n"); - XPT_GetXDRData(state, XPT_HEADER, &header, &hlen); - fprintf(stderr, "XDR header %d bytes at %p:", - hlen, header); - for (i = 0; i < hlen; i++) - fprintf(stderr, "%c%02x", i ? ',' : ' ', (uint8_t)header[i]); - fprintf(stderr, "\n"); - - XPT_GetXDRData(state, XPT_DATA, &data, &dlen); - - fprintf(stderr, "XDR data %d bytes at %p:", - dlen, data); - for (i = 0; i < dlen; i++) - fprintf(stderr, "%c%02x/%c", i ? ',' : ' ', (uint8_t)data[i], - (uint8_t)data[i]); - fprintf(stderr, "\n"); - - whole = (char*)malloc(dlen + hlen); - if (!whole) { - fprintf(stderr, "malloc %d failed!\n", dlen + hlen); - return 1; - } - - /* TRY_Q("malloc", (data2 = malloc(len))); */ - memcpy(whole, header, hlen); - memcpy(whole + hlen, data, dlen); - XPT_DestroyXDRState(state); - - TRY("NewState (DECODE)", (state = XPT_NewXDRState(XPT_DECODE, whole, - hlen + dlen))); - - TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor)); - XPT_SetDataOffset(state, sizeof input); - - if (XDR(arena, cursor, &output)) - return 1; - - dump_struct("after", &output); - XPT_DestroyXDRState(state); - XPT_DestroyArena(arena); - free(whole); - - return 0; -} diff --git a/xpcom/typelib/xpt/tests/SimpleTypeLib.cpp b/xpcom/typelib/xpt/tests/SimpleTypeLib.cpp deleted file mode 100644 index 4ce8e75e83..0000000000 --- a/xpcom/typelib/xpt/tests/SimpleTypeLib.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -/* Test the structure creation and serialization APIs from xpt_struct.c */ -#include - -#include "xpt_xdr.h" -#include "xpt_struct.h" - -#define PASS(msg) \ - fprintf(stderr, "PASSED : %s\n", msg); - -#define FAIL(msg) \ - fprintf(stderr, "FAILURE: %s\n", msg); - -#define TRY_(msg, cond, silent) \ - if ((cond) && !silent) { \ - PASS(msg); \ - } else { \ - FAIL(msg); \ - return 1; \ - } - -#define TRY(msg, cond) TRY_(msg, cond, 0) -#define TRY_Q(msg, cond) TRY_(msg, cond, 1); - -struct nsID iid = { - 0x00112233, - 0x4455, - 0x6677, - {0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff} -}; - -XPTTypeDescriptor td_void; - -int -main(int argc, char **argv) -{ - XPTArena *arena; - XPTHeader *header; - XPTAnnotation *ann; - XPTInterfaceDescriptor *id; - XPTMethodDescriptor *meth; - - XPTState *state; - XPTCursor curs, *cursor = &curs; - char *data, *head; - FILE *out; - uint32_t len, header_sz; - - PRBool ok; - - td_void.prefix.flags = TD_VOID; - - if (argc != 2) { - fprintf(stderr, "Usage: %s \n" - " Creates a simple typelib file.\n", argv[0]); - - return 1; - } - - arena = XPT_NewArena(1024, sizeof(double), "main"); - TRY("XPT_NewArena", arena); - - /* construct a header */ - header = XPT_NewHeader(arena, 1, XPT_MAJOR_VERSION, XPT_MINOR_VERSION); - TRY("NewHeader", header); - - - ann = XPT_NewAnnotation(arena, XPT_ANN_LAST | XPT_ANN_PRIVATE, - XPT_NewStringZ(arena, "SimpleTypeLib 1.0"), - XPT_NewStringZ(arena, "See You In Rome")); - TRY("NewAnnotation", ann); - header->annotations = ann; - - header_sz = XPT_SizeOfHeaderBlock(header); - - id = XPT_NewInterfaceDescriptor(arena, 0, 2, 2, 0); - TRY("NewInterfaceDescriptor", id); - - ok = XPT_FillInterfaceDirectoryEntry(arena, header->interface_directory, &iid, - "Interface", "NS", id); - TRY("FillInterfaceDirectoryEntry", ok); - - /* void method1(void) */ - meth = &id->method_descriptors[0]; - ok = XPT_FillMethodDescriptor(arena, meth, 0, "method1", 0); - TRY("FillMethodDescriptor", ok); - meth->result.flags = 0; - meth->result.type.prefix.flags = TD_VOID; - - /* wstring method2(in uint32_t, in bool) */ - meth = &id->method_descriptors[1]; - ok = XPT_FillMethodDescriptor(arena, meth, 0, "method2", 2); - TRY("FillMethodDescriptor", ok); - - meth->result.flags = 0; - meth->result.type.prefix.flags = TD_PSTRING | XPT_TDP_POINTER; - meth->params[0].type.prefix.flags = TD_UINT32; - meth->params[0].flags = XPT_PD_IN; - meth->params[1].type.prefix.flags = TD_BOOL; - meth->params[1].flags = XPT_PD_IN; - -#if 0 - /* const one = 1; */ - id->const_descriptors[0].name = "one"; - id->const_descriptors[0].type.prefix.flags = TD_UINT16; - id->const_descriptors[0].value.ui16 = 1; - - /* const squeamish = "ossifrage"; */ - id->const_descriptors[1].name = "squeamish"; - id->const_descriptors[1].type.prefix.flags = TD_PBSTR | XPT_TDP_POINTER; - id->const_descriptors[1].value.string = XPT_NewStringZ(arena, "ossifrage"); -#endif - - /* serialize it */ - state = XPT_NewXDRState(XPT_ENCODE, NULL, 0); - TRY("NewState (ENCODE)", state); - - ok = XPT_MakeCursor(state, XPT_HEADER, header_sz, cursor); - TRY("MakeCursor", ok); - - ok = XPT_DoHeader(arena, cursor, &header); - TRY("DoHeader", ok); - - out = fopen(argv[1], "wb"); - if (!out) { - perror("FAILED: fopen"); - return 1; - } - - XPT_GetXDRData(state, XPT_HEADER, &head, &len); - fwrite(head, len, 1, out); - - XPT_GetXDRData(state, XPT_DATA, &data, &len); - fwrite(data, len, 1, out); - - if (ferror(out) != 0 || fclose(out) != 0) { - fprintf(stderr, "\nError writing file: %s\n\n", argv[1]); - } else { - fprintf(stderr, "\nFile written: %s\n\n", argv[1]); - } - XPT_DestroyXDRState(state); - - XPT_FreeHeader(arena, header); - XPT_DestroyArena(arena); - - return 0; -} - diff --git a/xpcom/typelib/xpt/tests/moz.build b/xpcom/typelib/xpt/tests/moz.build deleted file mode 100644 index 8c1b94b09d..0000000000 --- a/xpcom/typelib/xpt/tests/moz.build +++ /dev/null @@ -1,14 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -SimplePrograms([ - 'PrimitiveTest', - 'SimpleTypeLib', -]) - -USE_LIBS += [ - 'xpt', -] diff --git a/xpcom/typelib/xpt/xpt_arena.cpp b/xpcom/typelib/xpt/xpt_arena.cpp index d9f9f6e81b..21be3c00bb 100644 --- a/xpcom/typelib/xpt/xpt_arena.cpp +++ b/xpcom/typelib/xpt/xpt_arena.cpp @@ -8,7 +8,6 @@ /* XXX This exists because we don't want to drag in NSPR. It *seemed* * to make more sense to write a quick and dirty arena than to clone * plarena (like js/src did). This is not optimal, but it works. -* Half of the code here is instrumentation. */ #include "xpt_arena.h" @@ -17,64 +16,12 @@ #include #include -/*************************/ -/* logging stats support */ - -#if 0 && defined(DEBUG_jband) -#define XPT_ARENA_LOGGING 1 -#endif - -#ifdef XPT_ARENA_LOGGING - -#define LOG_MALLOC(_a, _req, _used) \ - do{ \ - XPT_ASSERT((_a)); \ - ++(_a)->LOG_MallocCallCount; \ - (_a)->LOG_MallocTotalBytesRequested += (_req); \ - (_a)->LOG_MallocTotalBytesUsed += (_used); \ - } while(0) - -#define LOG_REAL_MALLOC(_a, _size) \ - do{ \ - XPT_ASSERT((_a)); \ - ++(_a)->LOG_RealMallocCallCount; \ - (_a)->LOG_RealMallocTotalBytesRequested += (_size); \ - } while(0) - -#define LOG_FREE(_a) \ - do{ \ - XPT_ASSERT((_a)); \ - ++(_a)->LOG_FreeCallCount; \ - } while(0) - -#define LOG_DONE_LOADING(_a) \ - do{ \ - XPT_ASSERT((_a)); \ - (_a)->LOG_LoadingFreeCallCount = (_a)->LOG_FreeCallCount; \ - } while(0) - -#define PRINT_STATS(_a) xpt_DebugPrintArenaStats((_a)) -static void xpt_DebugPrintArenaStats(XPTArena *arena); - -#else /* !XPT_ARENA_LOGGING */ - -#define LOG_MALLOC(_a, _req, _used) ((void)0) -#define LOG_REAL_MALLOC(_a, _size) ((void)0) -#define LOG_FREE(_a) ((void)0) - -#define LOG_DONE_LOADING(_a) ((void)0) -#define PRINT_STATS(_a) ((void)0) - -#endif /* XPT_ARENA_LOGGING */ - /****************************************************/ /* Block header for each block in the arena */ -typedef struct BLK_HDR BLK_HDR; struct BLK_HDR { BLK_HDR *next; - size_t size; }; #define XPT_MIN_BLOCK_SIZE 32 @@ -82,91 +29,66 @@ struct BLK_HDR /* XXX this is lame. Should clone the code to do this bitwise */ #define ALIGN_RND(s,a) ((a)==1?(s):((((s)+(a)-1)/(a))*(a))) -struct XPTArena +struct XPTSubArena { BLK_HDR *first; uint8_t *next; size_t space; - size_t alignment; size_t block_size; - char *name; +}; -#ifdef XPT_ARENA_LOGGING - uint32_t LOG_MallocCallCount; - uint32_t LOG_MallocTotalBytesRequested; - uint32_t LOG_MallocTotalBytesUsed; - uint32_t LOG_FreeCallCount; - uint32_t LOG_LoadingFreeCallCount; - uint32_t LOG_RealMallocCallCount; - uint32_t LOG_RealMallocTotalBytesRequested; -#endif /* XPT_ARENA_LOGGING */ +struct XPTArena +{ + // We have one sub-arena with 8-byte alignment for most allocations, and + // one with 1-byte alignment for C string allocations. The latter sub-arena + // avoids significant amounts of unnecessary padding between C strings. + XPTSubArena subarena8; + XPTSubArena subarena1; }; XPT_PUBLIC_API(XPTArena *) -XPT_NewArena(uint32_t block_size, size_t alignment, const char* name) +XPT_NewArena(size_t block_size8, size_t block_size1) { - XPTArena *arena = (XPTArena*)calloc(1, sizeof(XPTArena)); + XPTArena *arena = static_cast(calloc(1, sizeof(XPTArena))); if (arena) { - XPT_ASSERT(alignment); - if (alignment > sizeof(double)) - alignment = sizeof(double); - arena->alignment = alignment; + if (block_size8 < XPT_MIN_BLOCK_SIZE) + block_size8 = XPT_MIN_BLOCK_SIZE; + arena->subarena8.block_size = ALIGN_RND(block_size8, 8); - if (block_size < XPT_MIN_BLOCK_SIZE) - block_size = XPT_MIN_BLOCK_SIZE; - arena->block_size = ALIGN_RND(block_size, alignment); - - /* must have room for at least one item! */ - XPT_ASSERT(arena->block_size >= - ALIGN_RND(sizeof(BLK_HDR), alignment) + - ALIGN_RND(1, alignment)); - - if (name) { - arena->name = XPT_STRDUP(arena, name); -#ifdef XPT_ARENA_LOGGING - /* fudge the stats since we are using space in the arena */ - arena->LOG_MallocCallCount = 0; - arena->LOG_MallocTotalBytesRequested = 0; - arena->LOG_MallocTotalBytesUsed = 0; -#endif /* XPT_ARENA_LOGGING */ - } + if (block_size1 < XPT_MIN_BLOCK_SIZE) + block_size1 = XPT_MIN_BLOCK_SIZE; + arena->subarena1.block_size = block_size1; + } + return arena; +} + +static void +DestroySubArena(XPTSubArena *subarena) +{ + BLK_HDR* cur = subarena->first; + while (cur) { + BLK_HDR* next = cur->next; + free(cur); + cur = next; } - return arena; } XPT_PUBLIC_API(void) XPT_DestroyArena(XPTArena *arena) { - BLK_HDR* cur; - BLK_HDR* next; - - cur = arena->first; - while (cur) { - next = cur->next; - free(cur); - cur = next; - } + DestroySubArena(&arena->subarena8); + DestroySubArena(&arena->subarena1); free(arena); } -XPT_PUBLIC_API(void) -XPT_DumpStats(XPTArena *arena) -{ - PRINT_STATS(arena); -} - - /* * Our alignment rule is that we always round up the size of each allocation * so that the 'arena->next' pointer one will point to properly aligned space. */ XPT_PUBLIC_API(void *) -XPT_ArenaMalloc(XPTArena *arena, size_t size) +XPT_ArenaCalloc(XPTArena *arena, size_t size, size_t alignment) { - uint8_t *cur; - size_t bytes; - if (!size) return NULL; @@ -175,124 +97,67 @@ XPT_ArenaMalloc(XPTArena *arena, size_t size) return NULL; } - bytes = ALIGN_RND(size, arena->alignment); - - LOG_MALLOC(arena, size, bytes); + XPTSubArena *subarena; + if (alignment == 8) { + subarena = &arena->subarena8; + } else if (alignment == 1) { + subarena = &arena->subarena1; + } else { + XPT_ASSERT(0); + return NULL; + } - if (bytes > arena->space) { + size_t bytes = ALIGN_RND(size, alignment); + + if (bytes > subarena->space) { BLK_HDR* new_block; - size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), arena->alignment); - size_t new_space = arena->block_size; - - while (bytes > new_space - block_header_size) - new_space += arena->block_size; + size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), alignment); + size_t new_space = subarena->block_size; - new_block = (BLK_HDR*) calloc(new_space/arena->alignment, - arena->alignment); + while (bytes > new_space - block_header_size) + new_space += subarena->block_size; + + new_block = + static_cast(calloc(new_space / alignment, alignment)); if (!new_block) { - arena->next = NULL; - arena->space = 0; + subarena->next = NULL; + subarena->space = 0; return NULL; } - LOG_REAL_MALLOC(arena, new_space); - /* link block into the list of blocks for use when we destroy */ - new_block->next = arena->first; - arena->first = new_block; - - /* save other block header info */ - new_block->size = new_space; + new_block->next = subarena->first; + subarena->first = new_block; /* set info for current block */ - arena->next = ((uint8_t*)new_block) + block_header_size; - arena->space = new_space - block_header_size; + subarena->next = + reinterpret_cast(new_block) + block_header_size; + subarena->space = new_space - block_header_size; #ifdef DEBUG /* mark block for corruption check */ - memset(arena->next, 0xcd, arena->space); + memset(subarena->next, 0xcd, subarena->space); #endif - } - + } + #ifdef DEBUG { /* do corruption check */ size_t i; for (i = 0; i < bytes; ++i) { - XPT_ASSERT(arena->next[i] == 0xcd); + XPT_ASSERT(subarena->next[i] == 0xcd); } /* we guarantee that the block will be filled with zeros */ - memset(arena->next, 0, bytes); - } -#endif - - cur = arena->next; - arena->next += bytes; - arena->space -= bytes; - - return cur; -} - - -XPT_PUBLIC_API(char *) -XPT_ArenaStrDup(XPTArena *arena, const char * s) -{ - size_t len; - char* cur; - - if (!s) - return NULL; - - len = strlen(s)+1; - cur = (char*)XPT_ArenaMalloc(arena, len); - memcpy(cur, s, len); - return cur; -} - -XPT_PUBLIC_API(void) -XPT_NotifyDoneLoading(XPTArena *arena) -{ -#ifdef XPT_ARENA_LOGGING - if (arena) { - LOG_DONE_LOADING(arena); + memset(subarena->next, 0, bytes); } #endif -} -XPT_PUBLIC_API(void) -XPT_ArenaFree(XPTArena *arena, void *block) -{ - LOG_FREE(arena); -} + uint8_t* p = subarena->next; + subarena->next += bytes; + subarena->space -= bytes; -#ifdef XPT_ARENA_LOGGING -static void xpt_DebugPrintArenaStats(XPTArena *arena) -{ - printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n"); - printf("Start xpt arena stats for \"%s\"\n", - arena->name ? arena->name : "unnamed arena"); - printf("\n"); - printf("%d times arena malloc called\n", (int) arena->LOG_MallocCallCount); - printf("%d total bytes requested from arena malloc\n", (int) arena->LOG_MallocTotalBytesRequested); - printf("%d average bytes requested per call to arena malloc\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0); - printf("%d average bytes used per call (accounts for alignment overhead)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0); - printf("%d average bytes used per call (accounts for all overhead and waste)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_RealMallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0); - printf("\n"); - printf("%d during loading times arena free called\n", (int) arena->LOG_LoadingFreeCallCount); - printf("%d during loading approx total bytes not freed\n", (int) arena->LOG_LoadingFreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0)); - printf("\n"); - printf("%d total times arena free called\n", (int) arena->LOG_FreeCallCount); - printf("%d approx total bytes not freed until arena destruction\n", (int) arena->LOG_FreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0 )); - printf("\n"); - printf("%d times arena called system malloc\n", (int) arena->LOG_RealMallocCallCount); - printf("%d total bytes arena requested from system\n", (int) arena->LOG_RealMallocTotalBytesRequested); - printf("%d byte block size specified at arena creation time\n", (int) arena->block_size); - printf("%d byte block alignment specified at arena creation time\n", (int) arena->alignment); - printf("\n"); - printf("End xpt arena stats\n"); - printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n"); -} -#endif + return p; +} /***************************************************************************/ @@ -306,25 +171,26 @@ XPT_AssertFailed(const char *s, const char *file, uint32_t lineno) } #endif -XPT_PUBLIC_API(size_t) -XPT_SizeOfArena(XPTArena *arena, MozMallocSizeOf mallocSizeOf) +static size_t +SizeOfSubArenaExcludingThis(XPTSubArena *subarena, MozMallocSizeOf mallocSizeOf) { - size_t n = mallocSizeOf(arena); + size_t n = 0; - /* - * We don't measure arena->name separately because it's allocated out of - * the arena itself. - */ - - BLK_HDR* cur; - BLK_HDR* next; - - cur = arena->first; + BLK_HDR* cur = subarena->first; while (cur) { - next = cur->next; + BLK_HDR* next = cur->next; n += mallocSizeOf(cur); cur = next; } return n; } + +XPT_PUBLIC_API(size_t) +XPT_SizeOfArenaIncludingThis(XPTArena *arena, MozMallocSizeOf mallocSizeOf) +{ + size_t n = mallocSizeOf(arena); + n += SizeOfSubArenaExcludingThis(&arena->subarena8, mallocSizeOf); + n += SizeOfSubArenaExcludingThis(&arena->subarena1, mallocSizeOf); + return n; +} diff --git a/xpcom/typelib/xpt/xpt_arena.h b/xpcom/typelib/xpt/xpt_arena.h index 63f24afdc1..2e8f0195bc 100644 --- a/xpcom/typelib/xpt/xpt_arena.h +++ b/xpcom/typelib/xpt/xpt_arena.h @@ -35,50 +35,23 @@ extern "C" { typedef struct XPTArena XPTArena; XPT_PUBLIC_API(XPTArena *) -XPT_NewArena(uint32_t block_size, size_t alignment, const char* name); +XPT_NewArena(size_t block_size8, size_t block_size1); XPT_PUBLIC_API(void) XPT_DestroyArena(XPTArena *arena); -XPT_PUBLIC_API(void) -XPT_DumpStats(XPTArena *arena); - XPT_PUBLIC_API(void *) -XPT_ArenaMalloc(XPTArena *arena, size_t size); - -XPT_PUBLIC_API(char *) -XPT_ArenaStrDup(XPTArena *arena, const char * s); - -XPT_PUBLIC_API(void) -XPT_NotifyDoneLoading(XPTArena *arena); - -XPT_PUBLIC_API(void) -XPT_ArenaFree(XPTArena *arena, void* block); +XPT_ArenaCalloc(XPTArena *arena, size_t size, size_t alignment); XPT_PUBLIC_API(size_t) -XPT_SizeOfArena(XPTArena *arena, MozMallocSizeOf mallocSizeOf); +XPT_SizeOfArenaIncludingThis(XPTArena *arena, MozMallocSizeOf mallocSizeOf); /* --------------------------------------------------------- */ -#define XPT_MALLOC(_arena, _bytes) \ - XPT_ArenaMalloc((_arena), (_bytes)) - -#ifdef DEBUG -#define XPT_FREE(_arena, _ptr) \ - XPT_ArenaFree((_arena), (_ptr)) -#else -#define XPT_FREE(_arena, _ptr) \ - ((void)0) -#endif - -#define XPT_STRDUP(_arena, _s) \ - XPT_ArenaStrDup((_arena), (_s)) - -#define XPT_CALLOC(_arena, _size) XPT_MALLOC((_arena), (_size)) -#define XPT_NEW(_arena, _struct) ((_struct *) XPT_MALLOC((_arena), sizeof(_struct))) +#define XPT_CALLOC8(_arena, _bytes) XPT_ArenaCalloc((_arena), (_bytes), 8) +#define XPT_CALLOC1(_arena, _bytes) XPT_ArenaCalloc((_arena), (_bytes), 1) +#define XPT_NEW(_arena, _struct) ((_struct *) XPT_CALLOC8((_arena), sizeof(_struct))) #define XPT_NEWZAP(_arena, _struct) XPT_NEW((_arena), _struct) -#define XPT_DELETE(_arena, _ptr) do{XPT_FREE((_arena), (_ptr)); ((_ptr)) = NULL;}while(0) -#define XPT_FREEIF(_arena, _ptr) do{if ((_ptr)) XPT_FREE((_arena), (_ptr));}while(0) /* --------------------------------------------------------- */ diff --git a/xpcom/typelib/xpt/xpt_struct.cpp b/xpcom/typelib/xpt/xpt_struct.cpp index 361b437b2f..53332efde7 100644 --- a/xpcom/typelib/xpt/xpt_struct.cpp +++ b/xpcom/typelib/xpt/xpt_struct.cpp @@ -13,21 +13,9 @@ /***************************************************************************/ /* Forward declarations. */ -static uint32_t -SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id); - -static uint32_t -SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id); - -static uint32_t -SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id); - -static uint32_t -SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id); - static PRBool DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor, - XPTInterfaceDirectoryEntry *ide, uint16_t entry_index); + XPTInterfaceDirectoryEntry *ide); static PRBool DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd, @@ -38,7 +26,7 @@ DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md, XPTInterfaceDescriptor *id); static PRBool -DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp); +SkipAnnotation(XPTCursor *cursor, bool *isLast); static PRBool DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer, XPTInterfaceDescriptor **idp); @@ -56,262 +44,107 @@ DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd, /***************************************************************************/ -XPT_PUBLIC_API(uint32_t) -XPT_SizeOfHeader(XPTHeader *header) -{ - XPTAnnotation *ann, *last; - uint32_t size = 16 /* magic */ + - 1 /* major */ + 1 /* minor */ + - 2 /* num_interfaces */ + 4 /* file_length */ + - 4 /* interface_directory */ + 4 /* data_pool */; - - ann = header->annotations; - do { - size += 1; /* Annotation prefix */ - if (XPT_ANN_IS_PRIVATE(ann->flags)) - size += 2 + ann->creator->length + 2 + ann->private_data->length; - last = ann; - ann = ann->next; - } while (!XPT_ANN_IS_LAST(last->flags)); - - return size; -} - -XPT_PUBLIC_API(uint32_t) -XPT_SizeOfHeaderBlock(XPTHeader *header) -{ - uint32_t ide_size = 16 /* IID */ + 4 /* name */ + - 4 /* namespace */ + 4 /* descriptor */; - - return XPT_SizeOfHeader(header) + header->num_interfaces * ide_size; -} - -XPT_PUBLIC_API(XPTHeader *) -XPT_NewHeader(XPTArena *arena, uint16_t num_interfaces, uint8_t major_version, uint8_t minor_version) -{ - XPTHeader *header = XPT_NEWZAP(arena, XPTHeader); - if (!header) - return NULL; - memcpy(header->magic, XPT_MAGIC, 16); - header->major_version = major_version; - header->minor_version = minor_version; - header->num_interfaces = num_interfaces; - if (num_interfaces) { - header->interface_directory = - (XPTInterfaceDirectoryEntry*)XPT_CALLOC(arena, - num_interfaces * sizeof(XPTInterfaceDirectoryEntry)); - if (!header->interface_directory) { - XPT_DELETE(arena, header); - return NULL; - } - } - header->data_pool = 0; /* XXX do we even need this struct any more? */ - - return header; -} - -XPT_PUBLIC_API(void) -XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader) -{ - if (aHeader) { - XPTAnnotation* ann; - XPTInterfaceDirectoryEntry* entry = aHeader->interface_directory; - XPTInterfaceDirectoryEntry* end = entry + aHeader->num_interfaces; - for (; entry < end; entry++) { - XPT_DestroyInterfaceDirectoryEntry(arena, entry); - } - - ann = aHeader->annotations; - while (ann) { - XPTAnnotation* next = ann->next; - if (XPT_ANN_IS_PRIVATE(ann->flags)) { - XPT_FREEIF(arena, ann->creator); - XPT_FREEIF(arena, ann->private_data); - } - XPT_DELETE(arena, ann); - ann = next; - } - - XPT_FREEIF(arena, aHeader->interface_directory); - XPT_DELETE(arena, aHeader); - } -} - XPT_PUBLIC_API(PRBool) -XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, uint32_t * ide_offset) +XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp) { - XPTMode mode = cursor->state->mode; unsigned int i; - XPTHeader * header; + uint32_t file_length = 0; + uint32_t ide_offset; - if (mode == XPT_DECODE) { - header = XPT_NEWZAP(arena, XPTHeader); - if (!header) + XPTHeader* header = XPT_NEWZAP(arena, XPTHeader); + if (!header) + return PR_FALSE; + *headerp = header; + + uint8_t magic[16]; + for (i = 0; i < sizeof(magic); i++) { + if (!XPT_Do8(cursor, &magic[i])) return PR_FALSE; - *headerp = header; - } else { - header = *headerp; } - if (mode == XPT_ENCODE) { - /* IDEs appear after header, including annotations */ - if (ide_offset != NULL) - { - *ide_offset = XPT_SizeOfHeader(*headerp) + 1; /* one-based offset */ - } - header->data_pool = XPT_SizeOfHeaderBlock(*headerp); - XPT_SetDataOffset(cursor->state, header->data_pool); - } - - for (i = 0; i < sizeof(header->magic); i++) { - if (!XPT_Do8(cursor, &header->magic[i])) - goto error; - } - - if (mode == XPT_DECODE && - strncmp((const char*)header->magic, XPT_MAGIC, 16) != 0) - { + if (strncmp((const char*)magic, XPT_MAGIC, 16) != 0) { /* Require that the header contain the proper magic */ fprintf(stderr, "libxpt: bad magic header in input file; " "found '%s', expected '%s'\n", - header->magic, XPT_MAGIC_STRING); - goto error; - } - - if (!XPT_Do8(cursor, &header->major_version) || - !XPT_Do8(cursor, &header->minor_version)) { - goto error; + magic, XPT_MAGIC_STRING); + return PR_FALSE; } - if (mode == XPT_DECODE && - header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) { + if (!XPT_Do8(cursor, &header->major_version) || + !XPT_Do8(cursor, &header->minor_version)) { + return PR_FALSE; + } + + if (header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) { /* This file is newer than we are and set to an incompatible version * number. We must set the header state thusly and return. */ header->num_interfaces = 0; - header->file_length = 0; return PR_TRUE; } if (!XPT_Do16(cursor, &header->num_interfaces) || - !XPT_Do32(cursor, &header->file_length) || - (ide_offset != NULL && !XPT_Do32(cursor, ide_offset))) { - goto error; - } - return PR_TRUE; - /* XXX need to free child data sometimes! */ - XPT_ERROR_HANDLE(arena, header); -} - -XPT_PUBLIC_API(PRBool) -XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp) -{ - XPTMode mode = cursor->state->mode; - XPTHeader * header; - uint32_t ide_offset; - int i; - XPTAnnotation *ann, *next, **annp; - - if (!XPT_DoHeaderPrologue(arena, cursor, headerp, &ide_offset)) + !XPT_Do32(cursor, &file_length) || + !XPT_Do32(cursor, &ide_offset)) { return PR_FALSE; - header = *headerp; + } + /* * Make sure the file length reported in the header is the same size as * as our buffer unless it is zero (not set) */ - if (mode == XPT_DECODE && (header->file_length != 0 && - cursor->state->pool->allocated < header->file_length)) { + if (file_length != 0 && + cursor->state->pool_allocated < file_length) { fputs("libxpt: File length in header does not match actual length. File may be corrupt\n", stderr); - goto error; + return PR_FALSE; } - if (mode == XPT_ENCODE) - XPT_DataOffset(cursor->state, &header->data_pool); - if (!XPT_Do32(cursor, &header->data_pool)) - goto error; - if (mode == XPT_DECODE) - XPT_DataOffset(cursor->state, &header->data_pool); + uint32_t data_pool; + if (!XPT_Do32(cursor, &data_pool)) + return PR_FALSE; - if (mode == XPT_DECODE && header->num_interfaces) { - header->interface_directory = - (XPTInterfaceDirectoryEntry*)XPT_CALLOC(arena, header->num_interfaces * - sizeof(XPTInterfaceDirectoryEntry)); + XPT_SetDataOffset(cursor->state, data_pool); + + if (header->num_interfaces) { + size_t n = header->num_interfaces * sizeof(XPTInterfaceDirectoryEntry); + header->interface_directory = + static_cast(XPT_CALLOC8(arena, n)); if (!header->interface_directory) - goto error; + return PR_FALSE; } /* * Iterate through the annotations rather than recurring, to avoid blowing - * the stack on large xpt files. + * the stack on large xpt files. We don't actually store annotations, we + * just skip over them. */ - ann = next = header->annotations; - annp = &header->annotations; + bool isLast; do { - ann = next; - if (!DoAnnotation(arena, cursor, &ann)) - goto error; - if (mode == XPT_DECODE) { - /* - * Make sure that we store the address of the newly allocated - * annotation in the previous annotation's ``next'' slot, or - * header->annotations for the first one. - */ - *annp = ann; - annp = &ann->next; - } - next = ann->next; - } while (!XPT_ANN_IS_LAST(ann->flags)); + if (!SkipAnnotation(cursor, &isLast)) + return PR_FALSE; + } while (!isLast); /* shouldn't be necessary now, but maybe later */ XPT_SeekTo(cursor, ide_offset); for (i = 0; i < header->num_interfaces; i++) { if (!DoInterfaceDirectoryEntry(arena, cursor, - &header->interface_directory[i], - (uint16_t)(i + 1))) - goto error; + &header->interface_directory[i])) + return PR_FALSE; } return PR_TRUE; - - /* XXX need to free child data sometimes! */ - XPT_ERROR_HANDLE(arena, header); } -XPT_PUBLIC_API(PRBool) -XPT_FillInterfaceDirectoryEntry(XPTArena *arena, - XPTInterfaceDirectoryEntry *ide, - nsID *iid, const char *name, - const char *name_space, - XPTInterfaceDescriptor *descriptor) -{ - XPT_COPY_IID(ide->iid, *iid); - ide->name = name ? XPT_STRDUP(arena, name) : NULL; /* what good is it w/o a name? */ - ide->name_space = name_space ? XPT_STRDUP(arena, name_space) : NULL; - ide->interface_descriptor = descriptor; - return PR_TRUE; -} - -XPT_PUBLIC_API(void) -XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena, - XPTInterfaceDirectoryEntry* ide) -{ - if (ide) { - if (ide->name) XPT_FREE(arena, ide->name); - if (ide->name_space) XPT_FREE(arena, ide->name_space); - XPT_FreeInterfaceDescriptor(arena, ide->interface_descriptor); - } -} - /* InterfaceDirectoryEntry records go in the header */ PRBool DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor, - XPTInterfaceDirectoryEntry *ide, uint16_t entry_index) + XPTInterfaceDirectoryEntry *ide) { - XPTMode mode = cursor->state->mode; - + char* dummy_name_space; + /* write the IID in our cursor space */ if (!XPT_DoIID(cursor, &(ide->iid)) || @@ -319,100 +152,21 @@ DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor, cursor space */ !XPT_DoCString(arena, cursor, &(ide->name)) || - /* write the name_space string in the data pool, and the offset in our - cursor space */ - !XPT_DoCString(arena, cursor, &(ide->name_space)) || - - /* do InterfaceDescriptors -- later, only on encode (see below) */ + /* don't write the name_space string in the data pool, because we don't + * need it. Do write the offset in our cursor space */ + !XPT_DoCString(arena, cursor, &dummy_name_space, /* ignore = */ true) || + + /* do InterfaceDescriptors */ !DoInterfaceDescriptor(arena, cursor, &ide->interface_descriptor)) { - goto error; + return PR_FALSE; } - - if (mode == XPT_DECODE) - XPT_SetOffsetForAddr(cursor, ide, entry_index); return PR_TRUE; - - XPT_ERROR_HANDLE(arena, ide); } -XPT_PUBLIC_API(XPTInterfaceDescriptor *) -XPT_NewInterfaceDescriptor(XPTArena *arena, - uint16_t parent_interface, uint16_t num_methods, - uint16_t num_constants, uint8_t flags) -{ - - XPTInterfaceDescriptor *id = XPT_NEWZAP(arena, XPTInterfaceDescriptor); - if (!id) - return NULL; - - if (num_methods) { - id->method_descriptors = (XPTMethodDescriptor*)XPT_CALLOC(arena, num_methods * - sizeof(XPTMethodDescriptor)); - if (!id->method_descriptors) - goto free_id; - id->num_methods = num_methods; - } - - if (num_constants) { - id->const_descriptors = (XPTConstDescriptor*)XPT_CALLOC(arena, num_constants * - sizeof(XPTConstDescriptor)); - if (!id->const_descriptors) - goto free_meth; - id->num_constants = num_constants; - } - - if (parent_interface) { - id->parent_interface = parent_interface; - } else { - id->parent_interface = 0; - } - - id->flags = flags; - - return id; - - free_meth: - XPT_FREEIF(arena, id->method_descriptors); - free_id: - XPT_DELETE(arena, id); - return NULL; -} - -XPT_PUBLIC_API(void) -XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id) -{ - if (id) { - XPTMethodDescriptor *md, *mdend; - XPTConstDescriptor *cd, *cdend; - - /* Free up method descriptors */ - md = id->method_descriptors; - mdend = md + id->num_methods; - for (; md < mdend; md++) { - XPT_FREEIF(arena, md->name); - XPT_FREEIF(arena, md->params); - } - XPT_FREEIF(arena, id->method_descriptors); - - /* Free up const descriptors */ - cd = id->const_descriptors; - cdend = cd + id->num_constants; - for (; cd < cdend; cd++) { - XPT_FREEIF(arena, cd->name); - } - XPT_FREEIF(arena, id->const_descriptors); - - /* Free up type descriptors */ - XPT_FREEIF(arena, id->additional_types); - - XPT_DELETE(arena, id); - } -} - -XPT_PUBLIC_API(PRBool) -XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id, - uint16_t num) +static PRBool +InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id, + uint16_t num) { XPTTypeDescriptor *old = id->additional_types; XPTTypeDescriptor *new_; @@ -420,225 +174,83 @@ XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id, size_t new_size = (num * sizeof(XPTTypeDescriptor)) + old_size; /* XXX should grow in chunks to minimize alloc overhead */ - new_ = (XPTTypeDescriptor*)XPT_CALLOC(arena, new_size); + new_ = static_cast(XPT_CALLOC8(arena, new_size)); if (!new_) return PR_FALSE; if (old) { - if (old_size) - memcpy(new_, old, old_size); - XPT_FREE(arena, old); + memcpy(new_, old, old_size); } id->additional_types = new_; + + if (num + uint16_t(id->num_additional_types) > 256) + return PR_FALSE; + id->num_additional_types += num; return PR_TRUE; } -XPT_PUBLIC_API(PRBool) -XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id, - uint16_t num) -{ - XPTMethodDescriptor *old = id->method_descriptors; - XPTMethodDescriptor *new_; - size_t old_size = id->num_methods * sizeof(XPTMethodDescriptor); - size_t new_size = (num * sizeof(XPTMethodDescriptor)) + old_size; - - /* XXX should grow in chunks to minimize alloc overhead */ - new_ = (XPTMethodDescriptor*)XPT_CALLOC(arena, new_size); - if (!new_) - return PR_FALSE; - if (old) { - if (old_size) - memcpy(new_, old, old_size); - XPT_FREE(arena, old); - } - id->method_descriptors = new_; - id->num_methods += num; - return PR_TRUE; -} - -XPT_PUBLIC_API(PRBool) -XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id, - uint16_t num) -{ - XPTConstDescriptor *old = id->const_descriptors; - XPTConstDescriptor *new_; - size_t old_size = id->num_constants * sizeof(XPTConstDescriptor); - size_t new_size = (num * sizeof(XPTConstDescriptor)) + old_size; - - /* XXX should grow in chunks to minimize alloc overhead */ - new_ = (XPTConstDescriptor*)XPT_CALLOC(arena, new_size); - if (!new_) - return PR_FALSE; - if (old) { - if (old_size) - memcpy(new_, old, old_size); - XPT_FREE(arena, old); - } - id->const_descriptors = new_; - id->num_constants += num; - return PR_TRUE; -} - -uint32_t -SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id) -{ - uint32_t size = 1; /* prefix */ - - switch (XPT_TDP_TAG(td->prefix)) { - case TD_INTERFACE_TYPE: - size += 2; /* interface_index */ - break; - case TD_INTERFACE_IS_TYPE: - size += 1; /* argnum */ - break; - case TD_ARRAY: - size += 2 + SizeOfTypeDescriptor( - &id->additional_types[td->type.additional_type], id); - break; - case TD_PSTRING_SIZE_IS: - size += 2; /* argnum + argnum2 */ - break; - case TD_PWSTRING_SIZE_IS: - size += 2; /* argnum + argnum2 */ - break; - default: - /* nothing special */ - break; - } - return size; -} - -uint32_t -SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id) -{ - uint32_t i, size = 1 /* flags */ + 4 /* name */ + 1 /* num_args */; - - for (i = 0; i < md->num_args; i++) - size += 1 + SizeOfTypeDescriptor(&md->params[i].type, id); - - size += 1 + SizeOfTypeDescriptor(&md->result.type, id); - return size; -} - -uint32_t -SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id) -{ - uint32_t size = 4 /* name */ + SizeOfTypeDescriptor(&cd->type, id); - - switch (XPT_TDP_TAG(cd->type.prefix)) { - case TD_INT8: - case TD_UINT8: - case TD_CHAR: - size ++; - break; - case TD_INT16: - case TD_UINT16: - case TD_WCHAR: - size += 2; - break; - case TD_INT32: - case TD_UINT32: - case TD_PSTRING: - size += 4; - break; - case TD_INT64: - case TD_UINT64: - size += 8; - break; - default: - fprintf(stderr, "libxpt: illegal type in ConstDescriptor: 0x%02x\n", - XPT_TDP_TAG(cd->type.prefix)); - return 0; - } - - return size; -} - -uint32_t -SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id) -{ - uint32_t size = 2 /* parent interface */ + 2 /* num_methods */ - + 2 /* num_constants */ + 1 /* flags */, i; - for (i = 0; i < id->num_methods; i++) - size += SizeOfMethodDescriptor(&id->method_descriptors[i], id); - for (i = 0; i < id->num_constants; i++) - size += SizeOfConstDescriptor(&id->const_descriptors[i], id); - return size; -} - PRBool DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer, XPTInterfaceDescriptor **idp) { - XPTMode mode = outer->state->mode; XPTInterfaceDescriptor *id; XPTCursor curs, *cursor = &curs; uint32_t i, id_sz = 0; - if (mode == XPT_DECODE) { - id = XPT_NEWZAP(arena, XPTInterfaceDescriptor); - if (!id) - return PR_FALSE; - *idp = id; - } else { - id = *idp; - if (!id) { - id_sz = 0; - return XPT_Do32(outer, &id_sz); - } - id_sz = SizeOfInterfaceDescriptor(id); - } + id = XPT_NEWZAP(arena, XPTInterfaceDescriptor); + if (!id) + return PR_FALSE; + *idp = id; if (!XPT_MakeCursor(outer->state, XPT_DATA, id_sz, cursor)) - goto error; + return PR_FALSE; if (!XPT_Do32(outer, &cursor->offset)) - goto error; - if (mode == XPT_DECODE && !cursor->offset) { - XPT_DELETE(arena, *idp); + return PR_FALSE; + if (!cursor->offset) { return PR_TRUE; } if(!XPT_Do16(cursor, &id->parent_interface) || !XPT_Do16(cursor, &id->num_methods)) { - goto error; + return PR_FALSE; } - if (mode == XPT_DECODE && id->num_methods) { - id->method_descriptors = (XPTMethodDescriptor*)XPT_CALLOC(arena, id->num_methods * - sizeof(XPTMethodDescriptor)); + if (id->num_methods) { + size_t n = id->num_methods * sizeof(XPTMethodDescriptor); + id->method_descriptors = + static_cast(XPT_CALLOC8(arena, n)); if (!id->method_descriptors) - goto error; + return PR_FALSE; } for (i = 0; i < id->num_methods; i++) { if (!DoMethodDescriptor(arena, cursor, &id->method_descriptors[i], id)) - goto error; + return PR_FALSE; } if (!XPT_Do16(cursor, &id->num_constants)) { - goto error; + return PR_FALSE; } - if (mode == XPT_DECODE && id->num_constants) { - id->const_descriptors = (XPTConstDescriptor*)XPT_CALLOC(arena, id->num_constants * - sizeof(XPTConstDescriptor)); + if (id->num_constants) { + size_t n = id->num_constants * sizeof(XPTConstDescriptor); + id->const_descriptors = + static_cast(XPT_CALLOC8(arena, n)); if (!id->const_descriptors) - goto error; + return PR_FALSE; } for (i = 0; i < id->num_constants; i++) { if (!DoConstDescriptor(arena, cursor, &id->const_descriptors[i], id)) { - goto error; + return PR_FALSE; } } if (!XPT_Do8(cursor, &id->flags)) { - goto error; + return PR_FALSE; } - - return PR_TRUE; - XPT_ERROR_HANDLE(arena, id); + return PR_TRUE; } PRBool @@ -694,35 +306,10 @@ DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd, } -XPT_PUBLIC_API(PRBool) -XPT_FillMethodDescriptor(XPTArena *arena, XPTMethodDescriptor *meth, - uint8_t flags, const char *name, uint8_t num_args) -{ - meth->flags = flags & XPT_MD_FLAGMASK; - meth->name = XPT_STRDUP(arena, name); - if (!meth->name) - return PR_FALSE; - meth->num_args = num_args; - if (num_args) { - meth->params = (XPTParamDescriptor*)XPT_CALLOC(arena, num_args * sizeof(XPTParamDescriptor)); - if (!meth->params) - goto free_name; - } else { - meth->params = NULL; - } - return PR_TRUE; - - XPT_DELETE(arena, meth->params); - free_name: - XPT_DELETE(arena, meth->name); - return PR_FALSE; -} - PRBool DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md, XPTInterfaceDescriptor *id) { - XPTMode mode = cursor->state->mode; int i; if (!XPT_Do8(cursor, &md->flags) || @@ -730,32 +317,22 @@ DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md, !XPT_Do8(cursor, &md->num_args)) return PR_FALSE; - if (mode == XPT_DECODE && md->num_args) { - md->params = (XPTParamDescriptor*)XPT_CALLOC(arena, md->num_args * sizeof(XPTParamDescriptor)); + if (md->num_args) { + size_t n = md->num_args * sizeof(XPTParamDescriptor); + md->params = static_cast(XPT_CALLOC8(arena, n)); if (!md->params) return PR_FALSE; } for(i = 0; i < md->num_args; i++) { if (!DoParamDescriptor(arena, cursor, &md->params[i], id)) - goto error; + return PR_FALSE; } if (!DoParamDescriptor(arena, cursor, &md->result, id)) - goto error; + return PR_FALSE; return PR_TRUE; - - XPT_ERROR_HANDLE(arena, md->params); -} - -XPT_PUBLIC_API(PRBool) -XPT_FillParamDescriptor(XPTArena *arena, XPTParamDescriptor *pd, uint8_t flags, - XPTTypeDescriptor *type) -{ - pd->flags = flags & XPT_PD_FLAGMASK; - XPT_COPY_TYPE(pd->type, *type); - return PR_TRUE; } PRBool @@ -780,132 +357,69 @@ DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td, XPTInterfaceDescriptor *id) { if (!DoTypeDescriptorPrefix(arena, cursor, &td->prefix)) { - goto error; + return PR_FALSE; } switch (XPT_TDP_TAG(td->prefix)) { case TD_INTERFACE_TYPE: - if (!XPT_Do16(cursor, &td->type.iface)) - goto error; + uint16_t iface; + if (!XPT_Do16(cursor, &iface)) + return PR_FALSE; + td->u.iface.iface_hi8 = (iface >> 8) & 0xff; + td->u.iface.iface_lo8 = iface & 0xff; break; case TD_INTERFACE_IS_TYPE: - if (!XPT_Do8(cursor, &td->argnum)) - goto error; + if (!XPT_Do8(cursor, &td->u.interface_is.argnum)) + return PR_FALSE; break; - case TD_ARRAY: - if (!XPT_Do8(cursor, &td->argnum) || - !XPT_Do8(cursor, &td->argnum2)) - goto error; + case TD_ARRAY: { + // argnum2 appears in the on-disk format but it isn't used. + uint8_t argnum2 = 0; + if (!XPT_Do8(cursor, &td->u.array.argnum) || + !XPT_Do8(cursor, &argnum2)) + return PR_FALSE; - if (cursor->state->mode == XPT_DECODE) { - if(!XPT_InterfaceDescriptorAddTypes(arena, id, 1)) - goto error; - td->type.additional_type = id->num_additional_types - 1; - } + if (!InterfaceDescriptorAddTypes(arena, id, 1)) + return PR_FALSE; + td->u.array.additional_type = id->num_additional_types - 1; if (!DoTypeDescriptor(arena, cursor, - &id->additional_types[td->type.additional_type], + &id->additional_types[td->u.array.additional_type], id)) - goto error; + return PR_FALSE; break; + } case TD_PSTRING_SIZE_IS: - case TD_PWSTRING_SIZE_IS: - if (!XPT_Do8(cursor, &td->argnum) || - !XPT_Do8(cursor, &td->argnum2)) - goto error; + case TD_PWSTRING_SIZE_IS: { + // argnum2 appears in the on-disk format but it isn't used. + uint8_t argnum2 = 0; + if (!XPT_Do8(cursor, &td->u.pstring_is.argnum) || + !XPT_Do8(cursor, &argnum2)) + return PR_FALSE; break; - + } default: /* nothing special */ break; } return PR_TRUE; - - XPT_ERROR_HANDLE(arena, td); -} - -XPT_PUBLIC_API(XPTAnnotation *) -XPT_NewAnnotation(XPTArena *arena, uint8_t flags, XPTString *creator, - XPTString *private_data) -{ - XPTAnnotation *ann = XPT_NEWZAP(arena, XPTAnnotation); - if (!ann) - return NULL; - ann->flags = flags; - if (XPT_ANN_IS_PRIVATE(flags)) { - ann->creator = creator; - ann->private_data = private_data; - } - return ann; } PRBool -DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp) +SkipAnnotation(XPTCursor *cursor, bool *isLast) { - XPTMode mode = cursor->state->mode; - XPTAnnotation *ann; - - if (mode == XPT_DECODE) { - ann = XPT_NEWZAP(arena, XPTAnnotation); - if (!ann) - return PR_FALSE; - *annp = ann; - } else { - ann = *annp; - } - - if (!XPT_Do8(cursor, &ann->flags)) - goto error; + uint8_t flags; + if (!XPT_Do8(cursor, &flags)) + return PR_FALSE; - if (XPT_ANN_IS_PRIVATE(ann->flags)) { - if (!XPT_DoStringInline(arena, cursor, &ann->creator) || - !XPT_DoStringInline(arena, cursor, &ann->private_data)) - goto error_2; + *isLast = XPT_ANN_IS_LAST(flags); + + if (XPT_ANN_IS_PRIVATE(flags)) { + if (!XPT_SkipStringInline(cursor) || + !XPT_SkipStringInline(cursor)) + return PR_FALSE; } return PR_TRUE; - - error_2: - if (ann && XPT_ANN_IS_PRIVATE(ann->flags)) { - XPT_FREEIF(arena, ann->creator); - XPT_FREEIF(arena, ann->private_data); - } - XPT_ERROR_HANDLE(arena, ann); } -PRBool -XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block, - uint16_t num_interfaces, const char *name, - uint16_t *indexp) -{ - int i; - - for (i=1; i<=num_interfaces; i++) { - fprintf(stderr, "%s == %s ?\n", ide_block[i].name, name); - if (strcmp(ide_block[i].name, name) == 0) { - *indexp = i; - return PR_TRUE; - } - } - indexp = 0; - return PR_FALSE; -} - -static XPT_TYPELIB_VERSIONS_STRUCT versions[] = XPT_TYPELIB_VERSIONS; -#define XPT_TYPELIB_VERSIONS_COUNT (sizeof(versions) / sizeof(versions[0])) - -XPT_PUBLIC_API(uint16_t) -XPT_ParseVersionString(const char* str, uint8_t* major, uint8_t* minor) -{ - unsigned int i; - for (i = 0; i < XPT_TYPELIB_VERSIONS_COUNT; i++) { - if (!strcmp(versions[i].str, str)) { - *major = versions[i].major; - *minor = versions[i].minor; - return versions[i].code; - } - } - return XPT_VERSION_UNKNOWN; -} - - diff --git a/xpcom/typelib/xpt/xpt_struct.h b/xpcom/typelib/xpt/xpt_struct.h index 9ae0802432..b4da4a3fd0 100644 --- a/xpcom/typelib/xpt/xpt_struct.h +++ b/xpcom/typelib/xpt/xpt_struct.h @@ -35,8 +35,7 @@ typedef struct XPTMethodDescriptor XPTMethodDescriptor; typedef struct XPTParamDescriptor XPTParamDescriptor; typedef struct XPTTypeDescriptor XPTTypeDescriptor; typedef struct XPTTypeDescriptorPrefix XPTTypeDescriptorPrefix; -typedef struct XPTString XPTString; -typedef struct XPTAnnotation XPTAnnotation; + #ifndef nsID_h__ /* * We can't include nsID.h, because it's full of C++ goop and we're not doing @@ -53,32 +52,21 @@ struct nsID { typedef struct nsID nsID; #endif -#define XPT_COPY_IID(to, from) \ - (to).m0 = (from).m0; \ - (to).m1 = (from).m1; \ - (to).m2 = (from).m2; \ - (to).m3[0] = (from).m3[0]; \ - (to).m3[1] = (from).m3[1]; \ - (to).m3[2] = (from).m3[2]; \ - (to).m3[3] = (from).m3[3]; \ - (to).m3[4] = (from).m3[4]; \ - (to).m3[5] = (from).m3[5]; \ - (to).m3[6] = (from).m3[6]; \ - (to).m3[7] = (from).m3[7]; - - /* * Every XPCOM typelib file begins with a header. */ struct XPTHeader { - uint8_t magic[16]; + // Some of these fields exists in the on-disk format but don't need to be + // stored in memory (other than very briefly, which can be done with local + // variables). + + //uint8_t magic[16]; uint8_t major_version; uint8_t minor_version; uint16_t num_interfaces; - uint32_t file_length; + //uint32_t file_length; XPTInterfaceDirectoryEntry *interface_directory; - uint32_t data_pool; - XPTAnnotation *annotations; + //uint32_t data_pool; }; #define XPT_MAGIC "XPCOM\nTypeLib\r\n\032" @@ -87,90 +75,17 @@ struct XPTHeader { #define XPT_MAJOR_VERSION 0x01 #define XPT_MINOR_VERSION 0x02 -/* Any file with a major version number of XPT_MAJOR_INCOMPATIBLE_VERSION +/* Any file with a major version number of XPT_MAJOR_INCOMPATIBLE_VERSION * or higher is to be considered incompatible by this version of xpt and * we will refuse to read it. We will return a header with magic, major and - * minor versions set from the file. num_interfaces and file_length will be - * set to zero to confirm our inability to read the file; i.e. even if some - * client of this library gets out of sync with us regarding the agreed upon - * value for XPT_MAJOR_INCOMPATIBLE_VERSION, anytime num_interfaces and - * file_length are both zero we *know* that this library refused to read the - * file due to version imcompatibility. + * minor versions set from the file. num_interfaces will be set to zero to + * confirm our inability to read the file; i.e. even if some client of this + * library gets out of sync with us regarding the agreed upon value for + * XPT_MAJOR_INCOMPATIBLE_VERSION, anytime num_interfaces is zero we *know* + * that this library refused to read the file due to version incompatibility. */ #define XPT_MAJOR_INCOMPATIBLE_VERSION 0x02 -/* - * The "[-t version number]" cmd line parameter to the XPIDL compiler and XPT - * linker specifies the major and minor version number of the output - * type library. - * - * The goal is for the compiler to check that the input IDL file only uses - * constructs that are supported in the version specified. The linker will - * check that all typelib files it reads are of the version specified or - * below. - * - * Both the compiler and the linker will report errors and abort if these - * checks fail. - * - * When you rev up major or minor versions of the type library in the future, - * think about the new stuff that you added to the type library and add checks - * to make sure that occurrences of that new "stuff" will get caught when [-t - * version number] is used with the compiler. Here's what you'll probably - * have to do each time you rev up major/minor versions: - * - * 1) Add the current version number string (before your change) to the - * XPT_TYPELIB_VERSIONS list. - * - * 2) Do your changes add new features to XPIDL? Ensure that those new - * features are rejected by the XPIDL compiler when any version number in - * the XPT_TYPELIB_VERSIONS list is specified on the command line. The - * one place that currently does this kind of error checking is the function - * verify_type_fits_version() in xpidl_util.c. It currently checks - * attribute types, parameter types, and return types. You'll probably have - * to add to it or generalize it further based on what kind of changes you - * are making. - * - * 3) You will probably NOT need to make any changes to the error checking - * in the linker. - */ - -#define XPT_VERSION_UNKNOWN 0 -#define XPT_VERSION_UNSUPPORTED 1 -#define XPT_VERSION_OLD 2 -#define XPT_VERSION_CURRENT 3 - -typedef struct { - const char* str; - uint8_t major; - uint8_t minor; - uint16_t code; -} XPT_TYPELIB_VERSIONS_STRUCT; - -/* Currently accepted list of versions for typelibs */ -#define XPT_TYPELIB_VERSIONS { \ - {"1.0", 1, 0, XPT_VERSION_UNSUPPORTED}, \ - {"1.1", 1, 1, XPT_VERSION_OLD}, \ - {"1.2", 1, 2, XPT_VERSION_CURRENT} \ -} - -extern XPT_PUBLIC_API(uint16_t) -XPT_ParseVersionString(const char* str, uint8_t* major, uint8_t* minor); - -extern XPT_PUBLIC_API(XPTHeader *) -XPT_NewHeader(XPTArena *arena, uint16_t num_interfaces, - uint8_t major_version, uint8_t minor_version); - -extern XPT_PUBLIC_API(void) -XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader); - -/* size of header and annotations */ -extern XPT_PUBLIC_API(uint32_t) -XPT_SizeOfHeader(XPTHeader *header); - -/* size of header and annotations and InterfaceDirectoryEntries */ -extern XPT_PUBLIC_API(uint32_t) -XPT_SizeOfHeaderBlock(XPTHeader *header); - /* * A contiguous array of fixed-size InterfaceDirectoryEntry records begins at * the byte offset identified by the interface_directory field in the file @@ -180,29 +95,17 @@ XPT_SizeOfHeaderBlock(XPTHeader *header); struct XPTInterfaceDirectoryEntry { nsID iid; char *name; - char *name_space; - XPTInterfaceDescriptor *interface_descriptor; -#if 0 /* not yet */ - /* not stored on disk */ - uint32_t offset; /* the offset for an ID still to be read */ -#endif + // This field exists in the on-disk format. But it isn't used so we don't + // allocate space for it in memory. + //char *name_space; + + XPTInterfaceDescriptor *interface_descriptor; }; -extern XPT_PUBLIC_API(PRBool) -XPT_FillInterfaceDirectoryEntry(XPTArena *arena, - XPTInterfaceDirectoryEntry *ide, - nsID *iid, const char *name, - const char *name_space, - XPTInterfaceDescriptor *descriptor); - -extern XPT_PUBLIC_API(void) -XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena, - XPTInterfaceDirectoryEntry* ide); - /* - * An InterfaceDescriptor is a variable-size record used to describe a - * single XPCOM interface, including all of its methods. + * An InterfaceDescriptor describes a single XPCOM interface, including all of + * its methods. */ struct XPTInterfaceDescriptor { /* This field ordering minimizes the size of this struct. @@ -232,8 +135,7 @@ struct XPTInterfaceDescriptor { * them to be of fixed size. This additional_types scheme is here to allow * for that. */ - - uint16_t num_additional_types; + uint8_t num_additional_types; }; #define XPT_ID_SCRIPTABLE 0x80 @@ -247,46 +149,6 @@ struct XPTInterfaceDescriptor { #define XPT_ID_IS_BUILTINCLASS(flags) (!!(flags & XPT_ID_BUILTINCLASS)) #define XPT_ID_IS_MAIN_PROCESS_SCRIPTABLE_ONLY(flags) (!!(flags & XPT_ID_MAIN_PROCESS_SCRIPTABLE_ONLY)) -extern XPT_PUBLIC_API(PRBool) -XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block, - uint16_t num_interfaces, const char *name, - uint16_t *indexp); - -extern XPT_PUBLIC_API(XPTInterfaceDescriptor *) -XPT_NewInterfaceDescriptor(XPTArena *arena, - uint16_t parent_interface, uint16_t num_methods, - uint16_t num_constants, uint8_t flags); - -extern XPT_PUBLIC_API(void) -XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id); - -extern XPT_PUBLIC_API(PRBool) -XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id, - uint16_t num); - -extern XPT_PUBLIC_API(PRBool) -XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id, - uint16_t num); - -extern XPT_PUBLIC_API(PRBool) -XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id, - uint16_t num); - -/* - * This is our special string struct with a length value associated with it, - * which means that it can contains embedded NULs. - */ -struct XPTString { - uint16_t length; - char *bytes; -}; - -extern XPT_PUBLIC_API(XPTString *) -XPT_NewString(XPTArena *arena, uint16_t length, const char *bytes); - -extern XPT_PUBLIC_API(XPTString *) -XPT_NewStringZ(XPTArena *arena, const char *bytes); - /* * A TypeDescriptor is a variable-size record used to identify the type of a * method argument or return value. @@ -309,19 +171,12 @@ struct XPTTypeDescriptorPrefix { uint8_t flags; }; -/* flag bits -- fur and jband were right, I was miserably wrong */ - -// THESE TWO FLAGS ARE DEPRECATED. DO NOT USE THEM. See bug 692342. -#define XPT_TDP_POINTER 0x80 -#define XPT_TDP_REFERENCE 0x20 +/* flag bits */ #define XPT_TDP_FLAGMASK 0xe0 #define XPT_TDP_TAGMASK (~XPT_TDP_FLAGMASK) #define XPT_TDP_TAG(tdp) ((tdp).flags & XPT_TDP_TAGMASK) -#define XPT_TDP_IS_POINTER(flags) (flags & XPT_TDP_POINTER) -#define XPT_TDP_IS_REFERENCE(flags) (flags & XPT_TDP_REFERENCE) - /* * The following enum maps mnemonic names to the different numeric values * of XPTTypeDescriptor->tag. @@ -358,19 +213,39 @@ enum XPTTypeDescriptorTags { struct XPTTypeDescriptor { XPTTypeDescriptorPrefix prefix; - uint8_t argnum; /* used for iid_is and size_is */ - uint8_t argnum2; /* used for length_is */ - union { - uint16_t iface; /* used for TD_INTERFACE_TYPE */ - uint16_t additional_type; /* used for TD_ARRAY */ - } type; -}; -#define XPT_COPY_TYPE(to, from) \ - (to).prefix.flags = (from).prefix.flags; \ - (to).argnum = (from).argnum; \ - (to).argnum2 = (from).argnum2; \ - (to).type.additional_type = (from).type.additional_type; + // The memory layout here doesn't exactly match (for the appropriate types) + // the on-disk format. This is to save memory. + union { + // Used for TD_INTERFACE_IS_TYPE. + struct { + uint8_t argnum; + } interface_is; + + // Used for TD_PSTRING_SIZE_IS, TD_PWSTRING_SIZE_IS. + struct { + uint8_t argnum; + //uint8_t argnum2; // Present on disk, omitted here. + } pstring_is; + + // Used for TD_ARRAY. + struct { + uint8_t argnum; + //uint8_t argnum2; // Present on disk, omitted here. + uint8_t additional_type; // uint16_t on disk, uint8_t here; + // in practice it never exceeds 20. + } array; + + // Used for TD_INTERFACE_TYPE. + struct { + // We store the 16-bit iface value as two 8-bit values in order to + // avoid 16-bit alignment requirements for XPTTypeDescriptor, which + // reduces its size and also the size of XPTParamDescriptor. + uint8_t iface_hi8; + uint8_t iface_lo8; + } iface; + } u; +}; /* * A ConstDescriptor is a variable-size record that records the name and @@ -380,14 +255,12 @@ struct XPTTypeDescriptor { * of TypeDescriptors: * * int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, - * int64_t, uint64_t, wchar_t, char, string + * int64_t, uint64_t, wchar_t, char * * The type (and thus the size) of the value record is determined by the * contents of the associated TypeDescriptor record. For instance, if type * corresponds to int16_t, then value is a two-byte record consisting of a - * 16-bit signed integer. For a ConstDescriptor type of string, the value - * record is of type String*, i.e. an offset within the data pool to a - * String record containing the constant string. + * 16-bit signed integer. */ union XPTConstValue { int8_t i8; @@ -398,15 +271,8 @@ union XPTConstValue { uint32_t ui32; int64_t i64; uint64_t ui64; - float flt; - double dbl; - PRBool bul; char ch; uint16_t wch; - nsID *iid; - XPTString *string; - char *str; - uint16_t *wstr; }; /* varies according to type */ struct XPTConstDescriptor { @@ -424,7 +290,7 @@ struct XPTParamDescriptor { XPTTypeDescriptor type; }; -/* flag bits -- jband and fur were right, and I was miserably wrong */ +/* flag bits */ #define XPT_PD_IN 0x80 #define XPT_PD_OUT 0x40 #define XPT_PD_RETVAL 0x20 @@ -440,11 +306,6 @@ struct XPTParamDescriptor { #define XPT_PD_IS_DIPPER(flags) (flags & XPT_PD_DIPPER) #define XPT_PD_IS_OPTIONAL(flags) (flags & XPT_PD_OPTIONAL) -extern XPT_PUBLIC_API(PRBool) -XPT_FillParamDescriptor(XPTArena *arena, - XPTParamDescriptor *pd, uint8_t flags, - XPTTypeDescriptor *type); - /* * A MethodDescriptor is a variable-size record used to describe a single * interface method. @@ -457,11 +318,10 @@ struct XPTMethodDescriptor { uint8_t num_args; }; -/* flag bits -- jband and fur were right, and I was miserably wrong */ +/* flag bits */ #define XPT_MD_GETTER 0x80 #define XPT_MD_SETTER 0x40 #define XPT_MD_NOTXPCOM 0x20 -#define XPT_MD_CTOR 0x10 #define XPT_MD_HIDDEN 0x08 #define XPT_MD_OPT_ARGC 0x04 #define XPT_MD_CONTEXT 0x02 @@ -470,16 +330,10 @@ struct XPTMethodDescriptor { #define XPT_MD_IS_GETTER(flags) (flags & XPT_MD_GETTER) #define XPT_MD_IS_SETTER(flags) (flags & XPT_MD_SETTER) #define XPT_MD_IS_NOTXPCOM(flags) (flags & XPT_MD_NOTXPCOM) -#define XPT_MD_IS_CTOR(flags) (flags & XPT_MD_CTOR) #define XPT_MD_IS_HIDDEN(flags) (flags & XPT_MD_HIDDEN) #define XPT_MD_WANTS_OPT_ARGC(flags) (flags & XPT_MD_OPT_ARGC) #define XPT_MD_WANTS_CONTEXT(flags) (flags & XPT_MD_CONTEXT) -extern XPT_PUBLIC_API(PRBool) -XPT_FillMethodDescriptor(XPTArena *arena, - XPTMethodDescriptor *meth, uint8_t flags, - const char *name, uint8_t num_args); - /* * Annotation records are variable-size records used to store secondary * information about the typelib, e.g. such as the name of the tool that @@ -497,25 +351,16 @@ XPT_FillMethodDescriptor(XPTArena *arena, * EmptyAnnotation. EmptyAnnotation's are ignored - they're only used to * indicate an array of Annotation's that's completely empty. If the tag * is 1, the record is a PrivateAnnotation. + * + * We don't actually store annotations; we just skip over them if they are + * present. */ -struct XPTAnnotation { - XPTAnnotation *next; - uint8_t flags; - /* remaining fields are present in typelib iff XPT_ANN_IS_PRIVATE */ - XPTString *creator; - XPTString *private_data; -}; - #define XPT_ANN_LAST 0x80 #define XPT_ANN_IS_LAST(flags) (flags & XPT_ANN_LAST) #define XPT_ANN_PRIVATE 0x40 #define XPT_ANN_IS_PRIVATE(flags) (flags & XPT_ANN_PRIVATE) -extern XPT_PUBLIC_API(XPTAnnotation *) -XPT_NewAnnotation(XPTArena *arena, uint8_t flags, XPTString *creator, - XPTString *private_data); - } #endif /* __xpt_struct_h__ */ diff --git a/xpcom/typelib/xpt/xpt_xdr.cpp b/xpcom/typelib/xpt/xpt_xdr.cpp index e2e36b3a7c..2277e67d79 100644 --- a/xpcom/typelib/xpt/xpt_xdr.cpp +++ b/xpcom/typelib/xpt/xpt_xdr.cpp @@ -10,13 +10,6 @@ #include "nscore.h" #include /* strchr */ -static PRBool -CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, uint32_t len, - XPTCursor *new_cursor, PRBool *already); - -#define ENCODING(cursor) \ - ((cursor)->state->mode == XPT_ENCODE) - #define CURS_POOL_OFFSET_RAW(cursor) \ ((cursor)->pool == XPT_HEADER \ ? (cursor)->offset \ @@ -28,250 +21,36 @@ CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, uint32_t len, /* can be used as lvalue */ #define CURS_POINT(cursor) \ - ((cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)]) + ((cursor)->state->pool_data[CURS_POOL_OFFSET(cursor)]) -#if defined(DEBUG_shaver) || defined(DEBUG_jband) || defined(DEBUG_mccabe) -#define DBG(x) printf x -#else -#define DBG(x) (0) -#endif - -/* XXX fail if XPT_DATA and !state->data_offset */ -#define CHECK_COUNT_(cursor, space) \ - /* if we're in the header, then exceeding the data_offset is illegal */ \ -((cursor)->pool == XPT_HEADER ? \ - (ENCODING(cursor) && \ - ((cursor)->state->data_offset && \ - ((cursor)->offset - 1 + (space) > (cursor)->state->data_offset)) \ - ? (DBG(("no space left in HEADER %d + %d > %d\n", (cursor)->offset, \ - (space), (cursor)->state->data_offset)) && PR_FALSE) \ - : PR_TRUE) : \ - /* if we're in the data area and we're about to exceed the allocation */ \ - (CURS_POOL_OFFSET(cursor) + (space) > (cursor)->state->pool->allocated ? \ - /* then grow if we're in ENCODE mode */ \ - (ENCODING(cursor) ? GrowPool((cursor)->state->arena, \ - (cursor)->state->pool, \ - (cursor)->state->pool->allocated, \ - 0, CURS_POOL_OFFSET(cursor) + (space)) \ - /* and fail if we're in DECODE mode */ \ - : (DBG(("can't extend in DECODE")) && PR_FALSE)) \ - /* otherwise we're OK */ \ - : PR_TRUE)) - -#define CHECK_COUNT(cursor, space) \ - (CHECK_COUNT_(cursor, space) \ - ? PR_TRUE \ - : (XPT_ASSERT(0), \ - fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space), \ - PR_FALSE)) - -/* increase the data allocation for the pool by XPT_GROW_CHUNK */ -#define XPT_GROW_CHUNK 8192 - -/* - * quick and dirty hardcoded hashtable, to avoid dependence on nspr or glib. - * XXXmccabe it might turn out that we could use a simpler data structure here. - */ -typedef struct XPTHashRecord { - void *key; - void *value; - struct XPTHashRecord *next; -} XPTHashRecord; - -#define XPT_HASHSIZE 512 - -struct XPTHashTable { /* it's already typedef'ed from before. */ - XPTHashRecord *buckets[XPT_HASHSIZE]; - XPTArena *arena; -}; - -static XPTHashTable * -XPT_NewHashTable(XPTArena *arena) { - XPTHashTable *table; - table = XPT_NEWZAP(arena, XPTHashTable); - if (table) - table->arena = arena; - return table; -} - -static void trimrecord(XPTArena* arena, XPTHashRecord *record) { - if (record == NULL) - return; - trimrecord(arena, record->next); - XPT_DELETE(arena, record); -} - -static void -XPT_HashTableDestroy(XPTHashTable *table) { - int i; - for (i = 0; i < XPT_HASHSIZE; i++) - trimrecord(table->arena, table->buckets[i]); - XPT_FREE(table->arena, table); -} - -static void * -XPT_HashTableAdd(XPTHashTable *table, void *key, void *value) { - XPTHashRecord **bucketloc = table->buckets + - (NS_PTR_TO_UINT32(key) % XPT_HASHSIZE); - XPTHashRecord *bucket; - - while (*bucketloc != NULL) - bucketloc = &((*bucketloc)->next); - - bucket = XPT_NEW(table->arena, XPTHashRecord); - bucket->key = key; - bucket->value = value; - bucket->next = NULL; - *bucketloc = bucket; - return value; -} - -static void * -XPT_HashTableLookup(XPTHashTable *table, void *key) { - XPTHashRecord *bucket = table->buckets[NS_PTR_TO_UINT32(key) % XPT_HASHSIZE]; - while (bucket != NULL) { - if (bucket->key == key) - return bucket->value; - bucket = bucket->next; - } - return NULL; -} - -XPT_PUBLIC_API(XPTState *) -XPT_NewXDRState(XPTMode mode, char *data, uint32_t len) -{ - XPTState *state; - XPTArena *arena; - - arena = XPT_NewArena(512, sizeof(double), "an XDRState"); - if (!arena) - return NULL; - - state = XPT_NEWZAP(arena, XPTState); - if (!state) - goto err_free_arena; - - state->arena = arena; - state->mode = mode; - state->pool = XPT_NEW(arena, XPTDatapool); - state->next_cursor[0] = state->next_cursor[1] = 1; - if (!state->pool) - goto err_free_state; - - state->pool->count = 0; - state->pool->offset_map = XPT_NewHashTable(arena); - - if (!state->pool->offset_map) - goto err_free_pool; - if (mode == XPT_DECODE) { - state->pool->data = data; - state->pool->allocated = len; - } else { - state->pool->data = (char*)XPT_MALLOC(arena, XPT_GROW_CHUNK); - if (!state->pool->data) - goto err_free_hash; - state->pool->allocated = XPT_GROW_CHUNK; - } - - return state; - - err_free_hash: - XPT_HashTableDestroy(state->pool->offset_map); - err_free_pool: - XPT_DELETE(arena, state->pool); - err_free_state: - XPT_DELETE(arena, state); - err_free_arena: - if (arena) - XPT_DestroyArena(arena); - return NULL; -} - -XPT_PUBLIC_API(void) -XPT_DestroyXDRState(XPTState *state) -{ - XPTArena *arena = state->arena; - - if (state->pool->offset_map) - XPT_HashTableDestroy(state->pool->offset_map); - if (state->mode == XPT_ENCODE) - XPT_DELETE(arena, state->pool->data); - XPT_DELETE(arena, state->pool); - XPT_DELETE(arena, state); - if (arena) - XPT_DestroyArena(arena); -} - -XPT_PUBLIC_API(void) -XPT_GetXDRDataLength(XPTState *state, XPTPool pool, uint32_t *len) -{ - *len = state->next_cursor[pool] - 1; -} - -XPT_PUBLIC_API(void) -XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, uint32_t *len) -{ - if (pool == XPT_HEADER) { - *data = state->pool->data; - } else { - *data = state->pool->data + state->data_offset; - } - *len = state->next_cursor[pool] - 1; -} - -/* All offsets are 1-based */ -XPT_PUBLIC_API(void) -XPT_DataOffset(XPTState *state, uint32_t *data_offsetp) -{ - if (state->mode == XPT_DECODE) - XPT_SetDataOffset(state, *data_offsetp); - else - *data_offsetp = state->data_offset; -} - -/* if 'exact' is set use that, else grow by the next chunk but - * be sure to grow no less that 'at_least' so that we can't get - * behind on required space. - */ static PRBool -GrowPool(XPTArena *arena, XPTDatapool *pool, uint32_t old_size, - uint32_t exact, uint32_t at_least) +CHECK_COUNT(XPTCursor* cursor, uint32_t space) { - uint32_t total_size; - char *newdata; - - if (exact) { - XPT_ASSERT(exact > pool->allocated); - total_size = exact; - } else { - total_size = pool->allocated + XPT_GROW_CHUNK; - if (at_least > total_size) - total_size = at_least; - } - - newdata = (char*)XPT_MALLOC(arena, total_size); - if (!newdata) + // Fail if we're in the data area and about to exceed the allocation. + // XXX Also fail if we're in the data area and !state->data_offset + if (cursor->pool == XPT_DATA && + (CURS_POOL_OFFSET(cursor) + space > (cursor)->state->pool_allocated)) { + XPT_ASSERT(0); + fprintf(stderr, "FATAL: no room for %d in cursor\n", space); return PR_FALSE; - if (pool->data) { - if (old_size) - memcpy(newdata, pool->data, old_size); - XPT_FREE(arena, pool->data); } - pool->data = newdata; - pool->allocated = total_size; + return PR_TRUE; } +XPT_PUBLIC_API(void) +XPT_InitXDRState(XPTState* state, char *data, uint32_t len) +{ + state->next_cursor[0] = state->next_cursor[1] = 1; + state->pool_data = data; + state->pool_allocated = len; +} + +/* All offsets are 1-based */ XPT_PUBLIC_API(void) XPT_SetDataOffset(XPTState *state, uint32_t data_offset) { state->data_offset = data_offset; - /* make sure we've allocated enough space for the header */ - if (state->mode == XPT_ENCODE && - data_offset > state->pool->allocated) { - (void)GrowPool(state->arena, state->pool, state->pool->allocated, - data_offset, 0); - } } XPT_PUBLIC_API(PRBool) @@ -304,216 +83,60 @@ XPT_SeekTo(XPTCursor *cursor, uint32_t offset) return PR_TRUE; } -XPT_PUBLIC_API(XPTString *) -XPT_NewString(XPTArena *arena, uint16_t length, const char *bytes) -{ - XPTString *str = XPT_NEW(arena, XPTString); - if (!str) - return NULL; - str->length = length; - /* Alloc one extra to store the trailing nul. */ - str->bytes = (char*)XPT_MALLOC(arena, length + 1u); - if (!str->bytes) { - XPT_DELETE(arena, str); - return NULL; - } - memcpy(str->bytes, bytes, length); - /* nul-terminate it. */ - str->bytes[length] = '\0'; - return str; -} - -XPT_PUBLIC_API(XPTString *) -XPT_NewStringZ(XPTArena *arena, const char *bytes) -{ - uint32_t length = strlen(bytes); - if (length > 0xffff) - return NULL; /* too long */ - return XPT_NewString(arena, (uint16_t)length, bytes); -} - XPT_PUBLIC_API(PRBool) -XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp) +XPT_SkipStringInline(XPTCursor *cursor) { - XPTString *str = *strp; - XPTMode mode = cursor->state->mode; - int i; + uint16_t length; + if (!XPT_Do16(cursor, &length)) + return PR_FALSE; - if (mode == XPT_DECODE) { - str = XPT_NEWZAP(arena, XPTString); - if (!str) + uint8_t byte; + for (uint16_t i = 0; i < length; i++) + if (!XPT_Do8(cursor, &byte)) return PR_FALSE; - *strp = str; - } - - if (!XPT_Do16(cursor, &str->length)) - goto error; - - if (mode == XPT_DECODE) - if (!(str->bytes = (char*)XPT_MALLOC(arena, str->length + 1u))) - goto error; - - for (i = 0; i < str->length; i++) - if (!XPT_Do8(cursor, (uint8_t *)&str->bytes[i])) - goto error_2; - - if (mode == XPT_DECODE) - str->bytes[str->length] = 0; return PR_TRUE; - error_2: - XPT_DELETE(arena, str->bytes); - error: - XPT_DELETE(arena, str); - return PR_FALSE; } XPT_PUBLIC_API(PRBool) -XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp) +XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp, bool ignore) { - XPTCursor my_cursor; - XPTString *str = *strp; - PRBool already; - - XPT_PREAMBLE_NO_ALLOC(cursor, strp, XPT_DATA, str->length + 2u, my_cursor, - already) - - return XPT_DoStringInline(arena, &my_cursor, strp); -} - -XPT_PUBLIC_API(PRBool) -XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp) -{ - XPTCursor my_cursor; - char *ident = *identp; uint32_t offset = 0; + if (!XPT_Do32(cursor, &offset)) + return PR_FALSE; - XPTMode mode = cursor->state->mode; + if (!offset) { + *identp = NULL; + return PR_TRUE; + } - if (mode == XPT_DECODE) { - char *start, *end; - int len; + XPTCursor my_cursor; + my_cursor.pool = XPT_DATA; + my_cursor.offset = offset; + my_cursor.state = cursor->state; + char* start = &CURS_POINT(&my_cursor); - if (!XPT_Do32(cursor, &offset)) - return PR_FALSE; + char* end = strchr(start, 0); /* find the end of the string */ + if (!end) { + fprintf(stderr, "didn't find end of string on decode!\n"); + return PR_FALSE; + } + int len = end - start; + XPT_ASSERT(len > 0); - if (!offset) { - *identp = NULL; - return PR_TRUE; - } - - my_cursor.pool = XPT_DATA; - my_cursor.offset = offset; - my_cursor.state = cursor->state; - start = &CURS_POINT(&my_cursor); - - end = strchr(start, 0); /* find the end of the string */ - if (!end) { - fprintf(stderr, "didn't find end of string on decode!\n"); - return PR_FALSE; - } - len = end - start; - XPT_ASSERT(len > 0); - - ident = (char*)XPT_MALLOC(arena, len + 1u); + if (!ignore) { + char *ident = (char*)XPT_CALLOC1(arena, len + 1u); if (!ident) return PR_FALSE; memcpy(ident, start, (size_t)len); ident[len] = 0; *identp = ident; - - } else { - - if (!ident) { - offset = 0; - if (!XPT_Do32(cursor, &offset)) - return PR_FALSE; - return PR_TRUE; - } - - if (!XPT_MakeCursor(cursor->state, XPT_DATA, strlen(ident) + 1, - &my_cursor) || - !XPT_Do32(cursor, &my_cursor.offset)) - return PR_FALSE; - - while(*ident) - if (!XPT_Do8(&my_cursor, (uint8_t *)ident++)) - return PR_FALSE; - if (!XPT_Do8(&my_cursor, (uint8_t *)ident)) /* write trailing zero */ - return PR_FALSE; } return PR_TRUE; } -/* XXXjband it bothers me that this is one hashtable instead of two. - */ -XPT_PUBLIC_API(uint32_t) -XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr) -{ - XPTHashTable *table = cursor->state->pool->offset_map; - return NS_PTR_TO_UINT32(XPT_HashTableLookup(table, addr)); -} - -XPT_PUBLIC_API(PRBool) -XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, uint32_t offset) -{ - return XPT_HashTableAdd(cursor->state->pool->offset_map, - addr, NS_INT32_TO_PTR(offset)) != NULL; -} - -XPT_PUBLIC_API(PRBool) -XPT_SetAddrForOffset(XPTCursor *cursor, uint32_t offset, void *addr) -{ - return XPT_HashTableAdd(cursor->state->pool->offset_map, - NS_INT32_TO_PTR(offset), addr) != NULL; -} - -XPT_PUBLIC_API(void *) -XPT_GetAddrForOffset(XPTCursor *cursor, uint32_t offset) -{ - return XPT_HashTableLookup(cursor->state->pool->offset_map, - NS_INT32_TO_PTR(offset)); -} - -/* Used by XPT_PREAMBLE_NO_ALLOC. */ -static PRBool -CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, uint32_t len, - XPTCursor *new_cursor, PRBool *already) -{ - void *last = *addrp; - - *already = PR_FALSE; - new_cursor->state = cursor->state; - new_cursor->pool = pool; - new_cursor->bits = 0; - - if (cursor->state->mode == XPT_DECODE) { - - last = XPT_GetAddrForOffset(new_cursor, new_cursor->offset); - - if (last) { - *already = PR_TRUE; - *addrp = last; - } - - } else { - - new_cursor->offset = XPT_GetOffsetForAddr(new_cursor, last); - if (new_cursor->offset) { - *already = PR_TRUE; - return PR_TRUE; - } - - /* haven't already found it, so allocate room for it. */ - if (!XPT_MakeCursor(cursor->state, pool, len, new_cursor) || - !XPT_SetOffsetForAddr(new_cursor, *addrp, new_cursor->offset)) - return PR_FALSE; - } - return PR_TRUE; -} - /* * IIDs are written in struct order, in the usual big-endian way. From the * typelib file spec: @@ -552,7 +175,7 @@ XPT_Do64(XPTCursor *cursor, int64_t *u64p) } /* - * When we're writing 32- or 16-bit quantities, we write a byte at a time to + * When we're handling 32- or 16-bit quantities, we handle a byte at a time to * avoid alignment issues. Someone could come and optimize this to detect * well-aligned cases and do a single store, if they cared. I might care * later. @@ -568,25 +191,15 @@ XPT_Do32(XPTCursor *cursor, uint32_t *u32p) if (!CHECK_COUNT(cursor, 4)) return PR_FALSE; - if (ENCODING(cursor)) { - u.b32 = XPT_SWAB32(*u32p); - CURS_POINT(cursor) = u.b8[0]; - cursor->offset++; - CURS_POINT(cursor) = u.b8[1]; - cursor->offset++; - CURS_POINT(cursor) = u.b8[2]; - cursor->offset++; - CURS_POINT(cursor) = u.b8[3]; - } else { - u.b8[0] = CURS_POINT(cursor); - cursor->offset++; - u.b8[1] = CURS_POINT(cursor); - cursor->offset++; - u.b8[2] = CURS_POINT(cursor); - cursor->offset++; - u.b8[3] = CURS_POINT(cursor); - *u32p = XPT_SWAB32(u.b32); - } + u.b8[0] = CURS_POINT(cursor); + cursor->offset++; + u.b8[1] = CURS_POINT(cursor); + cursor->offset++; + u.b8[2] = CURS_POINT(cursor); + cursor->offset++; + u.b8[3] = CURS_POINT(cursor); + *u32p = XPT_SWAB32(u.b32); + cursor->offset++; return PR_TRUE; } @@ -602,17 +215,11 @@ XPT_Do16(XPTCursor *cursor, uint16_t *u16p) if (!CHECK_COUNT(cursor, 2)) return PR_FALSE; - if (ENCODING(cursor)) { - u.b16 = XPT_SWAB16(*u16p); - CURS_POINT(cursor) = u.b8[0]; - cursor->offset++; - CURS_POINT(cursor) = u.b8[1]; - } else { - u.b8[0] = CURS_POINT(cursor); - cursor->offset++; - u.b8[1] = CURS_POINT(cursor); - *u16p = XPT_SWAB16(u.b16); - } + u.b8[0] = CURS_POINT(cursor); + cursor->offset++; + u.b8[1] = CURS_POINT(cursor); + *u16p = XPT_SWAB16(u.b16); + cursor->offset++; return PR_TRUE; @@ -623,10 +230,8 @@ XPT_Do8(XPTCursor *cursor, uint8_t *u8p) { if (!CHECK_COUNT(cursor, 1)) return PR_FALSE; - if (cursor->state->mode == XPT_ENCODE) - CURS_POINT(cursor) = *u8p; - else - *u8p = CURS_POINT(cursor); + + *u8p = CURS_POINT(cursor); cursor->offset++; diff --git a/xpcom/typelib/xpt/xpt_xdr.h b/xpcom/typelib/xpt/xpt_xdr.h index 1966606c8f..c6d412b2ae 100644 --- a/xpcom/typelib/xpt/xpt_xdr.h +++ b/xpcom/typelib/xpt/xpt_xdr.h @@ -4,7 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* - * Basic APIs for streaming typelib structures to/from disk. + * Basic APIs for streaming typelib structures from disk. */ #ifndef __xpt_xdr_h__ @@ -17,20 +17,14 @@ extern "C" { #endif typedef struct XPTState XPTState; -typedef struct XPTDatapool XPTDatapool; typedef struct XPTCursor XPTCursor; -/* Opaque type, for internal use */ -typedef struct XPTHashTable XPTHashTable; +extern XPT_PUBLIC_API(PRBool) +XPT_SkipStringInline(XPTCursor *cursor); extern XPT_PUBLIC_API(PRBool) -XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp); - -extern XPT_PUBLIC_API(PRBool) -XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp); - -extern XPT_PUBLIC_API(PRBool) -XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **strp); +XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **strp, + bool ignore = false); extern XPT_PUBLIC_API(PRBool) XPT_DoIID(XPTCursor *cursor, nsID *iidp); @@ -47,34 +41,19 @@ XPT_Do16(XPTCursor *cursor, uint16_t *u16p); extern XPT_PUBLIC_API(PRBool) XPT_Do8(XPTCursor *cursor, uint8_t *u8p); -extern XPT_PUBLIC_API(PRBool) -XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, uint32_t * ide_offset); extern XPT_PUBLIC_API(PRBool) XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp); -typedef enum { - XPT_ENCODE, - XPT_DECODE -} XPTMode; - typedef enum { XPT_HEADER = 0, XPT_DATA = 1 } XPTPool; struct XPTState { - XPTMode mode; uint32_t data_offset; uint32_t next_cursor[2]; - XPTDatapool *pool; - XPTArena *arena; -}; - -struct XPTDatapool { - XPTHashTable *offset_map; - char *data; - uint32_t count; - uint32_t allocated; + char *pool_data; + uint32_t pool_allocated; }; struct XPTCursor { @@ -84,8 +63,8 @@ struct XPTCursor { uint8_t bits; }; -extern XPT_PUBLIC_API(XPTState *) -XPT_NewXDRState(XPTMode mode, char *data, uint32_t len); +extern XPT_PUBLIC_API(void) +XPT_InitXDRState(XPTState* state, char* data, uint32_t len); extern XPT_PUBLIC_API(PRBool) XPT_MakeCursor(XPTState *state, XPTPool pool, uint32_t len, XPTCursor *cursor); @@ -93,39 +72,9 @@ XPT_MakeCursor(XPTState *state, XPTPool pool, uint32_t len, XPTCursor *cursor); extern XPT_PUBLIC_API(PRBool) XPT_SeekTo(XPTCursor *cursor, uint32_t offset); -extern XPT_PUBLIC_API(void) -XPT_DestroyXDRState(XPTState *state); - -/* Set file_length based on the data used in the state. (Only ENCODE.) */ -extern XPT_PUBLIC_API(PRBool) -XPT_UpdateFileLength(XPTState *state); - -/* returns the length of the specified data block */ -extern XPT_PUBLIC_API(void) -XPT_GetXDRDataLength(XPTState *state, XPTPool pool, uint32_t *len); - -extern XPT_PUBLIC_API(void) -XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, uint32_t *len); - -/* set or get the data offset for the state, depending on mode */ -extern XPT_PUBLIC_API(void) -XPT_DataOffset(XPTState *state, uint32_t *data_offsetp); - extern XPT_PUBLIC_API(void) XPT_SetDataOffset(XPTState *state, uint32_t data_offset); -extern XPT_PUBLIC_API(uint32_t) -XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr); - -extern XPT_PUBLIC_API(PRBool) -XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, uint32_t offset); - -extern XPT_PUBLIC_API(PRBool) -XPT_SetAddrForOffset(XPTCursor *cursor, uint32_t offset, void *addr); - -extern XPT_PUBLIC_API(void *) -XPT_GetAddrForOffset(XPTCursor *cursor, uint32_t offset); - /* all data structures are big-endian */ #if defined IS_BIG_ENDIAN @@ -141,41 +90,6 @@ XPT_GetAddrForOffset(XPTCursor *cursor, uint32_t offset); # error "unknown byte order" #endif -/* - * If we're decoding, we want to read the offset before we check - * for already-decoded values. - * - * Then we check for repetition: CheckForRepeat will see if we've already - * encoded/decoded this value, and if so will set offset/addr correctly - * and make already be true. If not, it will set up the cursor for - * encoding (reserve space) or decoding (seek to correct location) as - * appropriate. In the encode case, it will also set the addr->offset - * mapping. - */ - -#define XPT_PREAMBLE_(cursor, addrp, pool, size, new_curs, already) \ - XPTMode mode = cursor->state->mode; \ - if (!(mode == XPT_ENCODE || XPT_Do32(cursor, &new_curs.offset)) || \ - !CheckForRepeat(cursor, (void **)addrp, pool, \ - mode == XPT_ENCODE ? size : 0u, &new_curs, \ - &already) || \ - !(mode == XPT_DECODE || XPT_Do32(cursor, &new_curs.offset))) \ - return PR_FALSE; \ - if (already) \ - return PR_TRUE; \ - -#define XPT_PREAMBLE_NO_ALLOC(cursor, addrp, pool, size, new_curs, already) \ - { \ - XPT_PREAMBLE_(cursor, addrp, pool, size, new_curs, already) \ - } - -#define XPT_ERROR_HANDLE(arena, free_it) \ - error: \ - if (cursor->state->mode == XPT_DECODE) \ - XPT_FREEIF(arena, free_it); \ - return PR_FALSE; - - #ifdef __cplusplus } #endif