author | Chris Jones <jones.chris.g@gmail.com> |
Thu, 28 Apr 2011 17:48:52 -0500 | |
changeset 69130 | 3dd6ec45084c7a79fbbae8aee42769a91dcf00ee |
parent 69129 | c8dcc08a4a8a02f006d2a8aa7f3e0ea9fc764fd1 |
child 69131 | 61bbaedfc2a3934a7fa821012756f6a3ee63046b |
push id | 76 |
push user | bzbarsky@mozilla.com |
push date | Tue, 05 Jul 2011 17:00:57 +0000 |
treeherder | mozilla-beta@d3a2732c35f1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jorendorff, luke |
bugs | 642381 |
milestone | 6.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -111,16 +111,18 @@ // Force PR_LOGGING so we can get JS strict warnings even in release builds #define FORCE_PR_LOG 1 #endif #include "prlog.h" #include "prthread.h" #include "mozilla/FunctionTimer.h" +using namespace mozilla; + const size_t gStackSize = 8192; #ifdef PR_LOGGING static PRLogModuleInfo* gJSDiagnostics; #endif // Thank you Microsoft! #ifndef WINCE @@ -1881,18 +1883,18 @@ nsJSContext::CallEventHandler(nsISupport jsval funval = OBJECT_TO_JSVAL(funobj); JSAutoEnterCompartment ac; if (!ac.enter(mContext, funobj) || !JS_WrapObject(mContext, &target)) { sSecurityManager->PopContextPrincipal(mContext); return NS_ERROR_FAILURE; } - js::Maybe<nsAutoPoolRelease> poolRelease; - js::Maybe<js::AutoArrayRooter> tvr; + Maybe<nsAutoPoolRelease> poolRelease; + Maybe<js::AutoArrayRooter> tvr; // Use |target| as the scope for wrapping the arguments, since aScope is // the safe scope in many cases, which isn't very useful. Wrapping aTarget // was OK because those typically have PreCreate methods that give them the // right scope anyway, and we want to make sure that the arguments end up // in the same scope as aTarget. rv = ConvertSupportsTojsvals(aargv, target, &argc, &argv, poolRelease, tvr); @@ -2370,18 +2372,18 @@ nsJSContext::InitializeExternalClasses() nsresult nsJSContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aArgs) { PRUint32 argc; jsval *argv = nsnull; JSAutoRequest ar(mContext); - js::Maybe<nsAutoPoolRelease> poolRelease; - js::Maybe<js::AutoArrayRooter> tvr; + Maybe<nsAutoPoolRelease> poolRelease; + Maybe<js::AutoArrayRooter> tvr; nsresult rv; rv = ConvertSupportsTojsvals(aArgs, GetNativeGlobal(), &argc, &argv, poolRelease, tvr); NS_ENSURE_SUCCESS(rv, rv); jsval vargs; @@ -2411,18 +2413,18 @@ nsJSContext::SetProperty(void *aTarget, return rv; } nsresult nsJSContext::ConvertSupportsTojsvals(nsISupports *aArgs, void *aScope, PRUint32 *aArgc, jsval **aArgv, - js::Maybe<nsAutoPoolRelease> &aPoolRelease, - js::Maybe<js::AutoArrayRooter> &aRooter) + Maybe<nsAutoPoolRelease> &aPoolRelease, + Maybe<js::AutoArrayRooter> &aRooter) { nsresult rv = NS_OK; // If the array implements nsIJSArgArray, just grab the values directly. nsCOMPtr<nsIJSArgArray> fastArray = do_QueryInterface(aArgs); if (fastArray != nsnull) return fastArray->GetArgs(aArgc, reinterpret_cast<void **>(aArgv));
--- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -46,16 +46,18 @@ #include "prtime.h" #include "nsCycleCollectionParticipant.h" #include "nsScriptNameSpaceManager.h" class nsIXPConnectJSObjectHolder; class nsAutoPoolRelease; namespace js { class AutoArrayRooter; +} +namespace mozilla { template <class> class Maybe; } class nsJSContext : public nsIScriptContext, public nsIXPCScriptNotify { public: nsJSContext(JSRuntime *aRuntime); @@ -200,18 +202,18 @@ public: protected: nsresult InitializeExternalClasses(); // Helper to convert xpcom datatypes to jsvals. nsresult ConvertSupportsTojsvals(nsISupports *aArgs, void *aScope, PRUint32 *aArgc, jsval **aArgv, - js::Maybe<nsAutoPoolRelease> &aPoolRelease, - js::Maybe<js::AutoArrayRooter> &aRooter); + mozilla::Maybe<nsAutoPoolRelease> &aPoolRelease, + mozilla::Maybe<js::AutoArrayRooter> &aRooter); nsresult AddSupportsPrimitiveTojsvals(nsISupports *aArg, jsval *aArgv); // given an nsISupports object (presumably an event target or some other // DOM object), get (or create) the JSObject wrapping it. nsresult JSObjectFromInterface(nsISupports *aSup, void *aScript, JSObject **aRet);
--- a/js/jetpack/JetpackActorCommon.cpp +++ b/js/jetpack/JetpackActorCommon.cpp @@ -35,36 +35,27 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "base/basictypes.h" #include "jscntxt.h" #include "jsapi.h" -#include "jstl.h" #include "jshashtable.h" #include "mozilla/jetpack/JetpackActorCommon.h" #include "mozilla/jetpack/PJetpack.h" #include "mozilla/jetpack/PHandleParent.h" #include "mozilla/jetpack/PHandleChild.h" #include "mozilla/jetpack/Handle.h" #include "nsJSUtils.h" -using mozilla::jetpack::JetpackActorCommon; -using mozilla::jetpack::PHandleParent; -using mozilla::jetpack::HandleParent; -using mozilla::jetpack::PHandleChild; -using mozilla::jetpack::HandleChild; -using mozilla::jetpack::KeyValue; -using mozilla::jetpack::PrimVariant; -using mozilla::jetpack::CompVariant; -using mozilla::jetpack::Variant; +using namespace mozilla::jetpack; class JetpackActorCommon::OpaqueSeenType { public: typedef JSObject* KeyType; typedef size_t IdType; typedef js::HashMap< KeyType, IdType, @@ -171,17 +162,17 @@ JetpackActorCommon::jsval_to_PrimVariant bool JetpackActorCommon::jsval_to_CompVariant(JSContext* cx, JSType type, jsval from, CompVariant* to, OpaqueSeenType* seen) { if (type != JSTYPE_OBJECT) return false; - js::Maybe<OpaqueSeenType> lost; + Maybe<OpaqueSeenType> lost; if (!seen) { lost.construct(); seen = lost.addr(); if (!seen->ok()) return false; } OpaqueSeenType::KeyType obj = JSVAL_TO_OBJECT(from); @@ -332,17 +323,17 @@ JetpackActorCommon::jsval_from_PrimVaria } bool JetpackActorCommon::jsval_from_CompVariant(JSContext* cx, const CompVariant& from, jsval* to, OpaqueSeenType* seen) { - js::Maybe<OpaqueSeenType> lost; + Maybe<OpaqueSeenType> lost; if (!seen) { lost.construct(); seen = lost.addr(); if (!seen->ok()) return false; } JSObject* obj = NULL;
--- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -287,16 +287,17 @@ EXPORTS_vm = \ # VPATH += \ $(srcdir)/../../mfbt \ $(NULL) EXPORTS_NAMESPACES += mozilla EXPORTS_mozilla = \ + Types.h \ Util.h \ $(NULL) ifdef ENABLE_TRACEJIT VPATH += \ $(srcdir)/tracejit \ $(srcdir)/nanojit \ @@ -723,16 +724,21 @@ distclean:: $(RM) $(DIST_GARBAGE) # our build system doesn't handle subdir srcs very gracefully today export:: $(MKDIR) -p nanojit DEFINES += -DEXPORT_JS_API +# mfbt is always packed with us, so if we're building a shared object, +# we need to declare "exported" mfbt symbols on its behalf when we use +# its headers. +DEFINES += -DIMPL_MFBT + # Some platforms that have stdint.h include it in system headers. So # to reliably get limit macros defined, we'd always have to define the # one below before including any header, but that's obscure and # fragile, so we do it here. DEFINES += -D__STDC_LIMIT_MACROS INCLUDES += -I$(srcdir)
--- a/js/src/jstl.h +++ b/js/src/jstl.h @@ -229,133 +229,16 @@ RoundUpPow2(size_t x) */ template <class T> JS_ALWAYS_INLINE size_t PointerRangeSize(T *begin, T *end) { return (size_t(end) - size_t(begin)) / sizeof(T); } -/* - * This utility pales in comparison to Boost's aligned_storage. The utility - * simply assumes that JSUint64 is enough alignment for anyone. This may need - * to be extended one day... - * - * As an important side effect, pulling the storage into this template is - * enough obfuscation to confuse gcc's strict-aliasing analysis into not giving - * false negatives when we cast from the char buffer to whatever type we've - * constructed using the bytes. - */ -template <size_t nbytes> -struct AlignedStorage -{ - union U { - char bytes[nbytes]; - uint64 _; - } u; - - const void *addr() const { return u.bytes; } - void *addr() { return u.bytes; } -}; - -template <class T> -struct AlignedStorage2 -{ - union U { - char bytes[sizeof(T)]; - uint64 _; - } u; - - const T *addr() const { return (const T *)u.bytes; } - T *addr() { return (T *)u.bytes; } -}; - -/* - * Small utility for lazily constructing objects without using dynamic storage. - * When a Maybe<T> is constructed, it is |empty()|, i.e., no value of T has - * been constructed and no T destructor will be called when the Maybe<T> is - * destroyed. Upon calling |construct|, a T object will be constructed with the - * given arguments and that object will be destroyed when the owning Maybe<T> - * is destroyed. - * - * N.B. GCC seems to miss some optimizations with Maybe and may generate extra - * branches/loads/stores. Use with caution on hot paths. - */ -template <class T> -class Maybe -{ - AlignedStorage2<T> storage; - bool constructed; - - T &asT() { return *storage.addr(); } - - explicit Maybe(const Maybe &other); - const Maybe &operator=(const Maybe &other); - - public: - Maybe() { constructed = false; } - ~Maybe() { if (constructed) asT().~T(); } - - bool empty() const { return !constructed; } - - void construct() { - JS_ASSERT(!constructed); - new(storage.addr()) T(); - constructed = true; - } - - template <class T1> - void construct(const T1 &t1) { - JS_ASSERT(!constructed); - new(storage.addr()) T(t1); - constructed = true; - } - - template <class T1, class T2> - void construct(const T1 &t1, const T2 &t2) { - JS_ASSERT(!constructed); - new(storage.addr()) T(t1, t2); - constructed = true; - } - - template <class T1, class T2, class T3> - void construct(const T1 &t1, const T2 &t2, const T3 &t3) { - JS_ASSERT(!constructed); - new(storage.addr()) T(t1, t2, t3); - constructed = true; - } - - template <class T1, class T2, class T3, class T4> - void construct(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) { - JS_ASSERT(!constructed); - new(storage.addr()) T(t1, t2, t3, t4); - constructed = true; - } - - T *addr() { - JS_ASSERT(constructed); - return &asT(); - } - - T &ref() { - JS_ASSERT(constructed); - return asT(); - } - - void destroy() { - ref().~T(); - constructed = false; - } - - void destroyIfConstructed() { - if (!empty()) - destroy(); - } -}; - template <class T> class AlignedPtrAndFlag { uintptr_t bits; public: AlignedPtrAndFlag(T *t, bool flag) { JS_ASSERT((uintptr_t(t) & 1) == 0);
--- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -41,16 +41,17 @@ * * ***** END LICENSE BLOCK ***** */ /* state and methods used while laying out a single line of a block frame */ #define PL_ARENA_CONST_ALIGN_MASK (sizeof(void*)-1) #include "plarena.h" +#include "mozilla/Util.h" #include "nsCOMPtr.h" #include "nsLineLayout.h" #include "nsBlockFrame.h" #include "nsInlineFrame.h" #include "nsStyleConsts.h" #include "nsHTMLContainerFrame.h" #include "nsFloatManager.h" #include "nsStyleContext.h" @@ -61,17 +62,16 @@ #include "nsIDocument.h" #include "nsIHTMLDocument.h" #include "nsIContent.h" #include "nsTextFragment.h" #include "nsBidiUtils.h" #include "nsLayoutUtils.h" #include "nsTextFrame.h" #include "nsCSSRendering.h" -#include "jstl.h" #ifdef DEBUG #undef NOISY_HORIZONTAL_ALIGN #undef NOISY_VERTICAL_ALIGN #undef REALLY_NOISY_VERTICAL_ALIGN #undef NOISY_REFLOW #undef REALLY_NOISY_REFLOW #undef NOISY_PUSHING @@ -79,16 +79,18 @@ #undef DEBUG_ADD_TEXT #undef NOISY_MAX_ELEMENT_SIZE #undef REALLY_NOISY_MAX_ELEMENT_SIZE #undef NOISY_CAN_PLACE_FRAME #undef NOISY_TRIM #undef REALLY_NOISY_TRIM #endif +using namespace mozilla; + //---------------------------------------------------------------------- #define FIX_BUG_50257 nsLineLayout::nsLineLayout(nsPresContext* aPresContext, nsFloatManager* aFloatManager, const nsHTMLReflowState* aOuterReflowState, const nsLineList::iterator* aLine) @@ -781,17 +783,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra // reflects the space left on the line. NS_WARN_IF_FALSE(psd->mRightEdge != NS_UNCONSTRAINEDSIZE, "have unconstrained width; this should only result from " "very large sizes, not attempts at intrinsic width " "calculation"); nscoord availableSpaceOnLine = psd->mRightEdge - psd->mX; // Setup reflow state for reflowing the frame - js::Maybe<nsHTMLReflowState> reflowStateHolder; + Maybe<nsHTMLReflowState> reflowStateHolder; if (!isText) { reflowStateHolder.construct(mPresContext, *psd->mReflowState, aFrame, availSize); nsHTMLReflowState& reflowState = reflowStateHolder.ref(); reflowState.mLineLayout = this; reflowState.mFlags.mIsTopOfPage = GetFlag(LL_ISTOPOFPAGE); if (reflowState.ComputedWidth() == NS_UNCONSTRAINEDSIZE) reflowState.availableWidth = availableSpaceOnLine;
new file mode 100644 --- /dev/null +++ b/mfbt/Types.h @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=99 ft=cpp: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Code. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyrigght (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * NB: This header must be both valid C and C++. It must be + * include-able by code embedding SpiderMonkey *and* Gecko. + */ + +#ifndef mozilla_Types_h_ +#define mozilla_Types_h_ + +/* + * mfbt is logically "lower level" than js/src, but needs basic + * definitions of numerical types and macros for compiler/linker + * directives. js/src already goes through some pain to provide them + * on numerous platforms, so instead of moving all that goop here, + * this header makes use of the fact that for the foreseeable future + * mfbt code will be part and parcel with libmozjs, static or not. + * + * For now, the policy is to use jstypes definitions but add a layer + * of indirection on top of them in case a Great Refactoring ever + * happens. + */ +#include "jstypes.h" + +/* + * The numerical types provided by jstypes.h that are allowed within + * mfbt code are + * + * stddef types: size_t, ptrdiff_t, etc. + * stdin [sic] types: int8, uint32, etc. + * + * stdint types (int8_t etc.), are available for use here, but doing + * so would change SpiderMonkey's and Gecko's contracts with + * embedders: stdint types have not yet appeared in public APIs. + */ + +#define MOZ_EXPORT_API(type_) JS_EXPORT_API(type_) +#define MOZ_IMPORT_API(type_) JS_IMPORT_API(type_) + +/* + * mfbt definitions need to see export declarations when built, but + * other code needs to see import declarations when using mfbt. + */ +#if defined(IMPL_MFBT) +# define MFBT_API(type_) MOZ_EXPORT_API(type_) +#else +# define MFBT_API(type_) MOZ_IMPORT_API(type_) +#endif + + +#define MOZ_BEGIN_EXTERN_C JS_BEGIN_EXTERN_C +#define MOZ_END_EXTERN_C JS_END_EXTERN_C + +#endif // mozilla_Types_h_
--- a/mfbt/Util.h +++ b/mfbt/Util.h @@ -35,16 +35,52 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #ifndef mozilla_Util_h_ #define mozilla_Util_h_ +#include "mozilla/Types.h" + +/* + * XXX: we're cheating here in order to avoid creating object files + * for mfbt /just/ to provide a function like FatalError() to be used + * by MOZ_ASSERT(). (It'll happen eventually, but for just ASSERT() + * it isn't worth the pain.) JS_Assert(), although unfortunately + * named, is part of SpiderMonkey's stable, external API, so this + * isn't quite as bad as it seems. + * + * Once mfbt needs object files, this unholy union with JS_Assert() + * will be broken. + */ +MOZ_BEGIN_EXTERN_C + +extern MFBT_API(void) +JS_Assert(const char *s, const char *file, JSIntn ln); + +MOZ_END_EXTERN_C + +/* + * MOZ_ASSERT() is a "strong" assertion of state, like libc's + * assert(). If a MOZ_ASSERT() fails in a debug build, the process in + * which it fails will stop running in a loud and dramatic way. + */ +#ifdef DEBUG + +# define MOZ_ASSERT(expr_) \ + ((expr_) ? (void)0 : JS_Assert(#expr_, __FILE__, __LINE__)) + +#else + +# define MOZ_ASSERT(expr_) ((void)0) + +#endif // DEBUG + #ifdef __cplusplus namespace mozilla { /** * DebugOnly contains a value of type T, but only in debug builds. In * release builds, it does not contain a value. This helper is * intended to be used along with ASSERT()-style macros, allowing one @@ -86,13 +122,131 @@ struct DebugOnly /* * DebugOnly must always have a destructor or else it will * generate "unused variable" warnings, exactly what it's intended * to avoid! */ ~DebugOnly() {} }; + +/* + * This utility pales in comparison to Boost's aligned_storage. The utility + * simply assumes that JSUint64 is enough alignment for anyone. This may need + * to be extended one day... + * + * As an important side effect, pulling the storage into this template is + * enough obfuscation to confuse gcc's strict-aliasing analysis into not giving + * false negatives when we cast from the char buffer to whatever type we've + * constructed using the bytes. + */ +template <size_t nbytes> +struct AlignedStorage +{ + union U { + char bytes[nbytes]; + uint64 _; + } u; + + const void *addr() const { return u.bytes; } + void *addr() { return u.bytes; } +}; + +template <class T> +struct AlignedStorage2 +{ + union U { + char bytes[sizeof(T)]; + uint64 _; + } u; + + const T *addr() const { return (const T *)u.bytes; } + T *addr() { return (T *)u.bytes; } +}; + +/* + * Small utility for lazily constructing objects without using dynamic storage. + * When a Maybe<T> is constructed, it is |empty()|, i.e., no value of T has + * been constructed and no T destructor will be called when the Maybe<T> is + * destroyed. Upon calling |construct|, a T object will be constructed with the + * given arguments and that object will be destroyed when the owning Maybe<T> + * is destroyed. + * + * N.B. GCC seems to miss some optimizations with Maybe and may generate extra + * branches/loads/stores. Use with caution on hot paths. + */ +template <class T> +class Maybe +{ + AlignedStorage2<T> storage; + bool constructed; + + T &asT() { return *storage.addr(); } + + explicit Maybe(const Maybe &other); + const Maybe &operator=(const Maybe &other); + + public: + Maybe() { constructed = false; } + ~Maybe() { if (constructed) asT().~T(); } + + bool empty() const { return !constructed; } + + void construct() { + MOZ_ASSERT(!constructed); + new(storage.addr()) T(); + constructed = true; + } + + template <class T1> + void construct(const T1 &t1) { + MOZ_ASSERT(!constructed); + new(storage.addr()) T(t1); + constructed = true; + } + + template <class T1, class T2> + void construct(const T1 &t1, const T2 &t2) { + MOZ_ASSERT(!constructed); + new(storage.addr()) T(t1, t2); + constructed = true; + } + + template <class T1, class T2, class T3> + void construct(const T1 &t1, const T2 &t2, const T3 &t3) { + MOZ_ASSERT(!constructed); + new(storage.addr()) T(t1, t2, t3); + constructed = true; + } + + template <class T1, class T2, class T3, class T4> + void construct(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) { + MOZ_ASSERT(!constructed); + new(storage.addr()) T(t1, t2, t3, t4); + constructed = true; + } + + T *addr() { + MOZ_ASSERT(constructed); + return &asT(); + } + + T &ref() { + MOZ_ASSERT(constructed); + return asT(); + } + + void destroy() { + ref().~T(); + constructed = false; + } + + void destroyIfConstructed() { + if (!empty()) + destroy(); + } +}; + } /* namespace mozilla */ #endif /* __cplusplus */ #endif /* mozilla_Util_h_ */