Bug 560723: Interpose non-throwing mozilla variants of VC10 STL functions that throw exceptions. r=ehsan sr=bsmedberg
authorChris Jones <jones.chris.g@gmail.com>
Wed, 28 Apr 2010 19:38:41 -0500
changeset 41511 6e7fe366cab7bd3aab5261df2837c66a8c824a8e
parent 41510 f8f7ca80f769db2fcf33ece4fcc90e1a2956d4f1
child 41512 2e62de00c6a31ef6917ac96654faff9dfa2b6476
push id13046
push userktomlinson@mozilla.com
push dateThu, 29 Apr 2010 00:41:45 +0000
treeherdermozilla-central@6e7fe366cab7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, bsmedberg
bugs560723
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
Bug 560723: Interpose non-throwing mozilla variants of VC10 STL functions that throw exceptions. r=ehsan sr=bsmedberg
config/autoconf.mk.in
config/stl-headers
configure.in
memory/mozalloc/Makefile.in
memory/mozalloc/msvc_raise_wrappers.cpp
memory/mozalloc/msvc_raise_wrappers.h
memory/mozalloc/msvc_throw_wrapper.cpp
memory/mozalloc/msvc_throw_wrapper.h
memory/mozalloc/throw_msvc.cpp
memory/mozalloc/throw_msvc.h
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -358,16 +358,18 @@ GNU_LD		= @GNU_LD@
 GNU_CC		= @GNU_CC@
 GNU_CXX		= @GNU_CXX@
 HAVE_GCC3_ABI	= @HAVE_GCC3_ABI@
 INTEL_CC	= @INTEL_CC@
 INTEL_CXX	= @INTEL_CXX@
 
 STL_FLAGS		= @STL_FLAGS@
 WRAP_STL_INCLUDES	= @WRAP_STL_INCLUDES@
+MOZ_MSVC_STL_WRAP__Throw= @MOZ_MSVC_STL_WRAP__Throw@
+MOZ_MSVC_STL_WRAP__RAISE= @MOZ_MSVC_STL_WRAP__RAISE@
 
 HOST_CC		= @HOST_CC@
 HOST_CXX	= @HOST_CXX@
 HOST_CFLAGS	= @HOST_CFLAGS@
 HOST_CXXFLAGS	= @HOST_CXXFLAGS@
 HOST_OPTIMIZE_FLAGS = @HOST_OPTIMIZE_FLAGS@
 HOST_NSPR_MDCPUCFG = @HOST_NSPR_MDCPUCFG@
 HOST_AR		= @HOST_AR@
--- a/config/stl-headers
+++ b/config/stl-headers
@@ -15,14 +15,15 @@
 new
 
 # FIXME: these headers haven't been reviewed yet, but we use them
 # unsafely in Gecko, so we might as well prevent them from
 # throwing exceptions
 algorithm
 deque
 iostream
+limits
 list
 map
 memory
 stack
 string
 vector
--- a/configure.in
+++ b/configure.in
@@ -708,38 +708,66 @@ EOF
                 AC_TRY_COMPILE([#include <exception>],
                             [std::_Throw(std::exception()); return 0;],
                             ac_cv_have_std__Throw="yes",
                             ac_cv_have_std__Throw="no")
                 CXXFLAGS="$_SAVE_CXXFLAGS"
                 AC_LANG_RESTORE
             ])
 
-        if test "$ac_cv_have_std__Throw" = "no"; then
-          AC_MSG_ERROR([Your MSVC/SDK doesn't export std::_Throw.  This breaks assumptions in Gecko.  Please file a bug describing this error along with your build configuration.])
+        if test "$ac_cv_have_std__Throw" == "yes"; then
+            AC_CACHE_CHECK(for |class __declspec(dllimport) exception| bug,
+                           ac_cv_have_dllimport_exception_bug,
+                [
+                    AC_LANG_SAVE
+                    AC_LANG_CPLUSPLUS
+                    _SAVE_CXXFLAGS="$CXXFLAGS"
+                    CXXFLAGS="${CXXFLAGS} -D_HAS_EXCEPTIONS=0"
+                    AC_TRY_LINK([#include <vector>],
+                                [std::vector<int> v; return v.at(1);],
+                                ac_cv_have_dllimport_exception_bug="no",
+                                ac_cv_have_dllimport_exception_bug="yes")
+                    CXXFLAGS="$_SAVE_CXXFLAGS"
+                    AC_LANG_RESTORE
+                ])
+            if test "$ac_cv_have_dllimport_exception_bug" = "no"; then
+                WRAP_STL_INCLUDES=1
+                MOZ_MSVC_STL_WRAP__Throw=1
+                AC_DEFINE(MOZ_MSVC_STL_WRAP__Throw)
+            fi
+        else
+            AC_CACHE_CHECK(for overridable _RAISE,
+                           ac_cv_have__RAISE,
+                [
+                    AC_LANG_SAVE
+                    AC_LANG_CPLUSPLUS
+                    _SAVE_CXXFLAGS="$CXXFLAGS"
+                    CXXFLAGS="${CXXFLAGS} -D_HAS_EXCEPTIONS=0"
+                    AC_TRY_COMPILE([#include <xstddef>
+                                    #undef _RAISE
+                                    #define _RAISE(x) externallyDefinedFunction((x).what())
+                                    #include <vector>
+                                   ],
+                                   [std::vector<int> v; return v.at(1);],
+                                   ac_cv_have__RAISE="no",
+                                   ac_cv_have__RAISE="yes")
+                    CXXFLAGS="$_SAVE_CXXFLAGS"
+                    AC_LANG_RESTORE
+                ])
+            if test "$ac_cv_have__RAISE" = "yes"; then
+                WRAP_STL_INCLUDES=1
+                MOZ_MSVC_STL_WRAP__RAISE=1
+                AC_DEFINE(MOZ_MSVC_STL_WRAP__RAISE)
+            else
+                AC_MSG_ERROR([Gecko exception wrapping doesn't understand your your MSVC/SDK.  Please file a bug describing this error and your build configuration.])
+            fi
         fi
 
-        AC_CACHE_CHECK(for |class __declspec(dllimport) exception| bug,
-                       ac_cv_have_dllimport_exception_bug,
-            [
-                AC_LANG_SAVE
-                AC_LANG_CPLUSPLUS
-                _SAVE_CXXFLAGS="$CXXFLAGS"
-                CXXFLAGS="${CXXFLAGS} -D_HAS_EXCEPTIONS=0"
-                AC_TRY_LINK([#include <vector>],
-                            [std::vector<int> v; return v.at(1);],
-                            ac_cv_have_dllimport_exception_bug="no",
-                            ac_cv_have_dllimport_exception_bug="yes")
-                CXXFLAGS="$_SAVE_CXXFLAGS"
-                AC_LANG_RESTORE
-            ])
-
-        if test "$ac_cv_have_dllimport_exception_bug" = "no"; then
+        if test "$WRAP_STL_INCLUDES" = "1"; then
             STL_FLAGS='-D_HAS_EXCEPTIONS=0 -I$(DIST)/stl_wrappers'
-            WRAP_STL_INCLUDES=1
         fi
     else
         # Check w32api version
         _W32API_MAJOR_VERSION=`echo $W32API_VERSION | $AWK -F\. '{ print $1 }'`
         _W32API_MINOR_VERSION=`echo $W32API_VERSION | $AWK -F\. '{ print $2 }'`
         AC_MSG_CHECKING([for w32api version >= $W32API_VERSION])
         AC_TRY_COMPILE([#include <w32api.h>],
             #if (__W32API_MAJOR_VERSION < $_W32API_MAJOR_VERSION) || \
@@ -841,16 +869,18 @@ AC_SUBST(GNU_AS)
 AC_SUBST(GNU_LD)
 AC_SUBST(GNU_CC)
 AC_SUBST(GNU_CXX)
 AC_SUBST(INTEL_CC)
 AC_SUBST(INTEL_CXX)
 
 AC_SUBST(STL_FLAGS)
 AC_SUBST(WRAP_STL_INCLUDES)
+AC_SUBST(MOZ_MSVC_STL_WRAP__Throw)
+AC_SUBST(MOZ_MSVC_STL_WRAP__RAISE)
 
 dnl ========================================================
 dnl Checks for programs.
 dnl ========================================================
 AC_PROG_INSTALL
 AC_PROG_LN_S
 
 if test -z "$TINDERBOX_SKIP_PERL_VERSION_CHECK"; then
--- a/memory/mozalloc/Makefile.in
+++ b/memory/mozalloc/Makefile.in
@@ -74,19 +74,30 @@ EXPORTS_mozilla 	=			\
 	$(NULL)
 
 CPPSRCS 		=			\
 	mozalloc.cpp				\
 	mozalloc_abort.cpp			\
 	mozalloc_oom.cpp			\
 	$(NULL)
 
-ifdef WRAP_STL_INCLUDES
-ifdef GCC_VERSION
+ifdef WRAP_STL_INCLUDES #{
+ifdef GCC_VERSION #{
 EXPORTS_mozilla	+= throw_gcc.h
-endif
-ifdef _MSC_VER
+else
+ifdef _MSC_VER #{
 EXPORTS_mozilla	+= throw_msvc.h
-CPPSRCS		+= throw_msvc.cpp
-endif
-endif  # WRAP_STL_INCLUDES
+ifdef MOZ_MSVC_STL_WRAP__Throw #{
+EXPORTS_mozilla	+= msvc_throw_wrapper.h
+CPPSRCS		+= msvc_throw_wrapper.cpp
+else
+ifdef MOZ_MSVC_STL_WRAP__RAISE #{
+EXPORTS_mozilla	+= msvc_raise_wrappers.h
+CPPSRCS		+= msvc_raise_wrappers.cpp
+else
+$(error Unknown STL wrapper tactic for MSVC)
+endif #}
+endif #}
+endif #}
+endif #}
+endif #}
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/memory/mozalloc/msvc_raise_wrappers.cpp
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ */
+/* ***** 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 Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * 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 ***** */
+
+#include <stdio.h>
+
+#if defined(XP_WIN) || (defined(XP_OS2) && defined(__declspec))
+#  define MOZALLOC_EXPORT __declspec(dllexport)
+#endif
+
+#define MOZALLOC_DONT_WRAP_RAISE_FUNCTIONS
+#include "mozilla/throw_msvc.h"
+
+__declspec(noreturn) static void abort_from_exception(const char* const which,
+                                                      const char* const what);
+static void
+abort_from_exception(const char* const which,  const char* const what)
+{
+    fprintf(stderr, "fatal: STL threw %s: ", which);
+    mozalloc_abort(what);
+}
+
+namespace std {
+
+// NB: user code is not supposed to touch the std:: namespace.  We're
+// doing this after careful review because we want to define our own
+// exception throwing semantics.  Don't try this at home!
+
+void
+moz_Xinvalid_argument(const char* what)
+{
+    abort_from_exception("invalid_argument", what);
+}
+
+void
+moz_Xlength_error(const char* what)
+{
+    abort_from_exception("length_error", what);
+}
+
+void
+moz_Xout_of_range(const char* what)
+{
+    abort_from_exception("out_of_range", what);
+}
+
+void
+moz_Xoverflow_error(const char* what)
+{
+    abort_from_exception("overflow_error", what);
+}
+
+void
+moz_Xruntime_error(const char* what)
+{
+    abort_from_exception("runtime_error", what);
+}
+
+}  // namespace std
new file mode 100644
--- /dev/null
+++ b/memory/mozalloc/msvc_raise_wrappers.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ */
+/* ***** 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 Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * 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 ***** */
+
+#ifndef mozilla_msvc_raise_wrappers_h
+#define mozilla_msvc_throw_wrappers_h
+
+#ifdef _XSTDDEF_
+#  error "Unable to wrap _RAISE(); CRT _RAISE() already defined"
+#endif
+#ifdef _XUTILITY_
+#  error "Unabled to wrap _X[exception]"(); CRT versions already declared"
+#endif
+
+#include "mozilla/mozalloc_abort.h"
+
+namespace std {
+
+// NB: user code is not supposed to touch the std:: namespace.  We're
+// doing this after careful review because we want to define our own
+// exception throwing semantics.  Don't try this at home!
+
+MOZALLOC_EXPORT __declspec(noreturn) void moz_Xinvalid_argument(const char*);
+MOZALLOC_EXPORT __declspec(noreturn) void moz_Xlength_error(const char*);
+MOZALLOC_EXPORT __declspec(noreturn) void moz_Xout_of_range(const char*);
+MOZALLOC_EXPORT __declspec(noreturn) void moz_Xoverflow_error(const char*);
+MOZALLOC_EXPORT __declspec(noreturn) void moz_Xruntime_error(const char*);
+
+} // namespace std
+
+#ifndef MOZALLOC_DONT_WRAP_RAISE_FUNCTIONS
+
+#  define _Xinvalid_argument  moz_Xinvalid_argument
+#  define _Xlength_error      moz_Xlength_error
+#  define _Xout_of_range      moz_Xout_of_range
+#  define _Xoverflow_error    moz_Xoverflow_error
+#  define _Xruntime_error     moz_Xruntime_error
+
+#  include <xstddef>
+#  include <xutility>
+
+#  undef _RAISE
+#  define _RAISE(x) mozalloc_abort((x).what())
+
+#endif  // ifndef MOZALLOC_DONT_WRAP_RAISE_FUNCTIONS
+
+#endif  // ifndef mozilla_msvc_raise_wrappers_h
rename from memory/mozalloc/throw_msvc.cpp
rename to memory/mozalloc/msvc_throw_wrapper.cpp
new file mode 100644
--- /dev/null
+++ b/memory/mozalloc/msvc_throw_wrapper.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ */
+/* ***** 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 Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * 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 ***** */
+
+#ifndef mozilla_msvc_throw_wrapper_h
+#define mozilla_msvc_throw_wrapper_h
+
+// Define our own _Throw because the Win2k CRT doesn't export it.
+#  ifdef _EXCEPTION_
+#    error "Unable to wrap _Throw(); CRT _Throw() already declared"
+#  endif
+#  define _Throw  mozilla_Throw
+#  include <exception>
+
+#endif  // ifndef mozilla_msvc_throw_wrapper_h
--- a/memory/mozalloc/throw_msvc.h
+++ b/memory/mozalloc/throw_msvc.h
@@ -36,19 +36,17 @@
  * 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_throw_msvc_h
 #define mozilla_throw_msvc_h
 
-// For MSVC, we define our own _Throw because the Win2k CRT doesn't
-// export it.
-
-#ifdef _EXCEPTION_
-#  error "Unable to wrap _Throw(); CRT _Throw() already declared"
+#if defined(MOZ_MSVC_STL_WRAP__RAISE)
+#  include "msvc_raise_wrappers.h"
+#elif defined(MOZ_MSVC_STL_WRAP__Throw)
+#  include "msvc_throw_wrapper.h"
+#else
+#  error "Unknown STL wrapper tactic"
 #endif
 
-#define _Throw  mozilla_Throw
-#include <exception>
-
 #endif  // mozilla_throw_msvc_h