Bug 711672 - Break mfbt's dependency on jstypes.h by moving various API macros out of JS and into mfbt. r=luke, r=cjones
authorJeff Walden <jwalden@mit.edu>
Tue, 13 Dec 2011 14:26:58 -0500
changeset 83743 38a35f0db9ff1bab21c7de76462fd06e50fa58cd
parent 83742 692d80735b7e90d94e595b20244891f85e73f7e0
child 83744 87be07cf8c10d4f8b9c0249529c6a4afa3983dac
push id628
push userclegnitto@mozilla.com
push dateWed, 21 Dec 2011 14:41:57 +0000
treeherdermozilla-aurora@24a61ad789e8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke, cjones
bugs711672
milestone11.0a1
Bug 711672 - Break mfbt's dependency on jstypes.h by moving various API macros out of JS and into mfbt. r=luke, r=cjones
js/public/TemplateLib.h
js/public/Utility.h
js/src/jstypes.h
js/src/jsutil.cpp
js/src/shell/js.cpp
js/xpconnect/shell/xpcshell.cpp
mfbt/Types.h
mfbt/Util.h
--- a/js/public/TemplateLib.h
+++ b/js/public/TemplateLib.h
@@ -36,18 +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 js_template_lib_h__
 #define js_template_lib_h__
 
-#include "mozilla/Types.h"
-#include "jsstdint.h"
+#include "jstypes.h"
 
 /*
  * Library of reusable template meta-functions (that is, functions on types and
  * compile-time values). Meta-functions are placed inside the 'tl' namespace to
  * avoid conflict with non-meta functions that logically have the same name
  * (e.g., js::tl::Min vs. js::Min).
  */
 
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -38,17 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef js_utility_h__
 #define js_utility_h__
 
 #include <stdlib.h>
 #include <string.h>
 
-#include "mozilla/Util.h"
+#include "jstypes.h"
 
 #ifdef __cplusplus
 
 /* The public JS engine namespace. */
 namespace JS {}
 
 /* The mozilla-shared reusable template/utility namespace. */
 namespace mozilla {}
--- a/js/src/jstypes.h
+++ b/js/src/jstypes.h
@@ -49,19 +49,18 @@
 ** Instead of requiring these authors to find the dependent uses in their code
 ** and take the following steps only in those C files, we take steps once here
 ** for all C files.
 **/
 
 #ifndef jstypes_h___
 #define jstypes_h___
 
-#include "mozilla/StdInt.h"
+#include "mozilla/Util.h"
 
-#include <stddef.h>
 #include "js-config.h"
 
 /***********************************************************************
 ** MACROS:      JS_EXTERN_API
 **              JS_EXPORT_API
 ** DESCRIPTION:
 **      These are only for externally visible routines and globals.  For
 **      internal routines, just use "extern" for type checking and that
@@ -75,82 +74,37 @@
 **   in dowhim.h
 **     JS_EXTERN_API( void ) DoWhatIMean( void );
 **   in dowhim.c
 **     JS_EXPORT_API( void ) DoWhatIMean( void ) { return; }
 **
 **
 ***********************************************************************/
 
-#if defined(WIN32) || defined(XP_OS2)
-
-/* These also work for __MWERKS__ */
-# define JS_EXTERN_API(__type)  extern __declspec(dllexport) __type
-# define JS_EXPORT_API(__type)  __declspec(dllexport) __type
-# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type
-# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type
-
-#else /* Unix */
-
-# ifdef HAVE_VISIBILITY_ATTRIBUTE
-#  define JS_EXTERNAL_VIS __attribute__((visibility ("default")))
-# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-#  define JS_EXTERNAL_VIS __global
-# else
-#  define JS_EXTERNAL_VIS
-# endif
-
-# define JS_EXTERN_API(__type)  extern JS_EXTERNAL_VIS __type
-# define JS_EXPORT_API(__type)  JS_EXTERNAL_VIS __type
-# define JS_EXTERN_DATA(__type) extern JS_EXTERNAL_VIS __type
-# define JS_EXPORT_DATA(__type) JS_EXTERNAL_VIS __type
-
-#endif
-
-#ifdef _WIN32
-# if defined(__MWERKS__) || defined(__GNUC__)
-#  define JS_IMPORT_API(__x)    __x
-# else
-#  define JS_IMPORT_API(__x)    __declspec(dllimport) __x
-# endif
-#elif defined(XP_OS2)
-# define JS_IMPORT_API(__x)     __declspec(dllimport) __x
-#else
-# define JS_IMPORT_API(__x)     JS_EXPORT_API (__x)
-#endif
-
-#if defined(_WIN32) && !defined(__MWERKS__)
-# define JS_IMPORT_DATA(__x)      __declspec(dllimport) __x
-#elif defined(XP_OS2)
-# define JS_IMPORT_DATA(__x)      __declspec(dllimport) __x
-#else
-# define JS_IMPORT_DATA(__x)     JS_EXPORT_DATA (__x)
-#endif
+#define JS_EXTERN_API(type)  extern MOZ_EXPORT_API(type)
+#define JS_EXPORT_API(type)  MOZ_EXPORT_API(type)
+#define JS_EXPORT_DATA(type) MOZ_EXPORT_DATA(type)
+#define JS_IMPORT_API(type)  MOZ_IMPORT_API(type)
+#define JS_IMPORT_DATA(type) MOZ_IMPORT_DATA(type)
 
 /*
  * The linkage of JS API functions differs depending on whether the file is
  * used within the JS library or not. Any source file within the JS
  * interpreter should define EXPORT_JS_API whereas any client of the library
  * should not. STATIC_JS_API is used to build JS as a static library.
  */
 #if defined(STATIC_JS_API)
-
-# define JS_PUBLIC_API(t)   t
-# define JS_PUBLIC_DATA(t)  t
-
+#  define JS_PUBLIC_API(t)   t
+#  define JS_PUBLIC_DATA(t)  t
 #elif defined(EXPORT_JS_API) || defined(STATIC_EXPORTABLE_JS_API)
-
-# define JS_PUBLIC_API(t)   JS_EXPORT_API(t)
-# define JS_PUBLIC_DATA(t)  JS_EXPORT_DATA(t)
-
+#  define JS_PUBLIC_API(t)   MOZ_EXPORT_API(t)
+#  define JS_PUBLIC_DATA(t)  MOZ_EXPORT_DATA(t)
 #else
-
-# define JS_PUBLIC_API(t)   JS_IMPORT_API(t)
-# define JS_PUBLIC_DATA(t)  JS_IMPORT_DATA(t)
-
+#  define JS_PUBLIC_API(t)   MOZ_IMPORT_API(t)
+#  define JS_PUBLIC_DATA(t)  MOZ_IMPORT_DATA(t)
 #endif
 
 #define JS_FRIEND_API(t)    JS_PUBLIC_API(t)
 #define JS_FRIEND_DATA(t)   JS_PUBLIC_DATA(t)
 
 #if defined(_MSC_VER) && defined(_M_IX86)
 #define JS_FASTCALL __fastcall
 #elif defined(__GNUC__) && defined(__i386__) &&                         \
@@ -240,27 +194,18 @@
 #endif
 
 /***********************************************************************
 ** MACROS:      JS_BEGIN_EXTERN_C
 **              JS_END_EXTERN_C
 ** DESCRIPTION:
 **      Macro shorthands for conditional C++ extern block delimiters.
 ***********************************************************************/
-#ifdef __cplusplus
-
-# define JS_BEGIN_EXTERN_C      extern "C" {
-# define JS_END_EXTERN_C        }
-
-#else
-
-# define JS_BEGIN_EXTERN_C
-# define JS_END_EXTERN_C
-
-#endif
+#define JS_BEGIN_EXTERN_C      MOZ_BEGIN_EXTERN_C
+#define JS_END_EXTERN_C        MOZ_END_EXTERN_C
 
 /***********************************************************************
 ** MACROS:      JS_BIT
 **              JS_BITMASK
 ** DESCRIPTION:
 ** Bit masking macros.  XXX n must be <= 31 to be portable
 ***********************************************************************/
 #define JS_BIT(n)       ((uint32_t)1 << (n))
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -48,16 +48,18 @@
 #include "jsutil.h"
 
 #ifdef WIN32
 #    include "jswin.h"
 #else
 #    include <signal.h>
 #endif
 
+#include "js/TemplateLib.h"
+
 using namespace js;
 
 #ifdef DEBUG
 /* For JS_OOM_POSSIBLY_FAIL in jsutil.h. */
 JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations = UINT32_MAX;
 JS_PUBLIC_DATA(uint32_t) OOM_counter = 0;
 #endif
 
@@ -91,17 +93,26 @@ CrashInJS()
      */
     *((volatile int *) NULL) = 123;  /* To continue from here in GDB: "return" then "continue". */
     raise(SIGABRT);  /* In case above statement gets nixed by the optimizer. */
 #else
     raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */
 #endif
 }
 
-JS_PUBLIC_API(void) JS_Assert(const char *s, const char *file, JSIntn ln)
+/*
+ * |JS_Assert| historically took |JSIntn ln| as its last argument.  We've
+ * boiled |JSIntn ln| down to simply |int ln| so that mfbt may declare the
+ * function without depending on the |JSIntn| typedef, so we must manually
+ * verify that the |JSIntn| typedef is consistent.
+ */
+JS_STATIC_ASSERT((tl::IsSameType<JSIntn, int>::result));
+
+JS_PUBLIC_API(void)
+JS_Assert(const char *s, const char *file, int ln)
 {
     fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
     fflush(stderr);
     CrashInJS();
 }
 
 #ifdef JS_BASIC_STATS
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -226,18 +226,18 @@ NewContext(JSRuntime *rt);
 static void
 DestroyContext(JSContext *cx, bool withGC);
 
 static const JSErrorFormatString *
 my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
 
 #ifdef EDITLINE
 JS_BEGIN_EXTERN_C
-JS_EXTERN_API(char)    *readline(const char *prompt);
-JS_EXTERN_API(void)     add_history(char *line);
+extern JS_EXPORT_API(char *) readline(const char *prompt);
+extern JS_EXPORT_API(void)   add_history(char *line);
 JS_END_EXTERN_C
 #endif
 
 static void
 ReportException(JSContext *cx)
 {
     if (JS_IsExceptionPending(cx)) {
         if (!JS_ReportPendingException(cx))
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -241,17 +241,17 @@ GetLocationProperty(JSContext *cx, JSObj
     }
 
     return true;
 #endif
 }
 
 #ifdef EDITLINE
 extern "C" {
-extern JS_EXPORT_API(char)     *readline(const char *prompt);
+extern JS_EXPORT_API(char *)   readline(const char *prompt);
 extern JS_EXPORT_API(void)     add_history(char *line);
 }
 #endif
 
 static JSBool
 GetLine(JSContext *cx, char *bufp, FILE *file, const char *prompt) {
 #ifdef EDITLINE
     /*
--- a/mfbt/Types.h
+++ b/mfbt/Types.h
@@ -32,56 +32,130 @@
  * 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.
- */
+/* mfbt foundational types and macros. */
 
 #ifndef mozilla_Types_h_
 #define mozilla_Types_h_
 
 /*
- * Expose the standard integer types from <stdint.h> (and the integer type
- * limit and constant macros, if the right __STDC_*_MACRO has been defined for
- * each).  These are all usable throughout mfbt code, and throughout Mozilla
- * code more generally.
+ * This header must be valid C and C++, includable by code embedding either
+ * SpiderMonkey or Gecko.
+ */
+
+/*
+ * Expose all the integer types defined in C99's <stdint.h> (and the integer
+ * limit and constant macros, if compiling C code or if compiling C++ code and
+ * the right __STDC_*_MACRO has been defined for each).  These are all usable
+ * throughout mfbt code, and throughout Mozilla code more generally.
  */
 #include "mozilla/StdInt.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.
+/* Also expose size_t. */
+#include <stddef.h>
+
+/* Implement compiler and linker macros needed for APIs. */
+
+/*
+ * MOZ_EXPORT_API is used to declare and define a method which is externally
+ * visible to users of the current library.  It encapsulates various decorations
+ * needed to properly export the method's symbol.  MOZ_EXPORT_DATA serves the
+ * same purpose for data.
+ *
+ *   api.h:
+ *     extern MOZ_EXPORT_API(int) MeaningOfLife(void);
+ *     extern MOZ_EXPORT_DATA(int) LuggageCombination;
+ *
+ *   api.c:
+ *     MOZ_EXPORT_API(int) MeaningOfLife(void) { return 42; }
+ *     MOZ_EXPORT_DATA(int) LuggageCombination = 12345;
  *
- * 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.
+ * If you are merely sharing a method across files, just use plain |extern|.
+ * These macros are designed for use by library interfaces -- not for normal
+ * methods or data used cross-file.
  */
-#include "jstypes.h"
-
-#define MOZ_EXPORT_API(type_)  JS_EXPORT_API(type_)
-#define MOZ_IMPORT_API(type_)  JS_IMPORT_API(type_)
+#if defined(WIN32) || defined(XP_OS2)
+#  define MOZ_EXPORT_API(type)    __declspec(dllexport) type
+#  define MOZ_EXPORT_DATA(type)   __declspec(dllexport) type
+#else /* Unix */
+#  ifdef HAVE_VISIBILITY_ATTRIBUTE
+#    define MOZ_EXTERNAL_VIS       __attribute__((visibility("default")))
+#  elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#    define MOZ_EXTERNAL_VIS      __global
+#  else
+#    define MOZ_EXTERNAL_VIS
+#  endif
+#  define MOZ_EXPORT_API(type)    MOZ_EXTERNAL_VIS type
+#  define MOZ_EXPORT_DATA(type)   MOZ_EXTERNAL_VIS type
+#endif
 
 /*
- * mfbt definitions need to see export declarations when built, but
- * other code needs to see import declarations when using mfbt.
+ * Whereas implementers use MOZ_EXPORT_API and MOZ_EXPORT_DATA to declare and
+ * define library symbols, users use MOZ_IMPORT_API and MOZ_IMPORT_DATA to
+ * access them.  Most often the implementer of the library will expose an API
+ * macro which expands to either the export or import version of the macro,
+ * depending upon the compilation mode.
+ */
+#ifdef _WIN32
+#  if defined(__MWERKS__) || defined(__GNUC__)
+#    define MOZ_IMPORT_API(x)    x
+#  else
+#    define MOZ_IMPORT_API(x)    __declspec(dllimport) x
+#  endif
+#elif defined(XP_OS2)
+#  define MOZ_IMPORT_API(x)     __declspec(dllimport) x
+#else
+#  define MOZ_IMPORT_API(x)     MOZ_EXPORT_API(x)
+#endif
+
+#if defined(_WIN32) && !defined(__MWERKS__)
+#  define MOZ_IMPORT_DATA(x)     __declspec(dllimport) x
+#elif defined(XP_OS2)
+#  define MOZ_IMPORT_DATA(x)     __declspec(dllimport) x
+#else
+#  define MOZ_IMPORT_DATA(x)     MOZ_EXPORT_DATA(x)
+#endif
+
+/*
+ * Consistent with the above comment, the MFBT_API and MFBT_DATA macros expose
+ * export mfbt declarations when building mfbt, and they expose import mfbt
+ * declarations when using mfbt.
  */
 #if defined(IMPL_MFBT)
-#  define MFBT_API(type_)       MOZ_EXPORT_API(type_)
+#  define MFBT_API(type)        MOZ_EXPORT_API(type)
+#  define MFBT_DATA(type)       MOZ_EXPORT_DATA(type)
 #else
-#  define MFBT_API(type_)       MOZ_IMPORT_API(type_)
+#  define MFBT_API(type)        MOZ_IMPORT_API(type)
+#  define MFBT_DATA(type)       MOZ_IMPORT_DATA(type)
 #endif
 
-
-#define MOZ_BEGIN_EXTERN_C     JS_BEGIN_EXTERN_C
-#define MOZ_END_EXTERN_C       JS_END_EXTERN_C
+/*
+ * C symbols in C++ code must be declared immediately within |extern "C"|
+ * blocks.  However, in C code, they need not be declared specially.  This
+ * difference is abstracted behind the MOZ_BEGIN_EXTERN_C and MOZ_END_EXTERN_C
+ * macros, so that the user need not know whether he is being used in C or C++
+ * code.
+ *
+ *   MOZ_BEGIN_EXTERN_C
+ *
+ *   extern MOZ_EXPORT_API(int) MostRandomNumber(void);
+ *   ...other declarations...
+ *
+ *   MOZ_END_EXTERN_C
+ *
+ * This said, it is preferable to just use |extern "C"| in C++ header files for
+ * its greater clarity.
+ */
+#ifdef __cplusplus
+#  define MOZ_BEGIN_EXTERN_C    extern "C" {
+#  define MOZ_END_EXTERN_C      }
+#else
+#  define MOZ_BEGIN_EXTERN_C
+#  define MOZ_END_EXTERN_C
+#endif
 
 #endif  /* mozilla_Types_h_ */
--- a/mfbt/Util.h
+++ b/mfbt/Util.h
@@ -54,17 +54,17 @@
  * will be broken.
  *
  * JS_Assert is present even in release builds, for the benefit of applications
  * that build DEBUG and link against a non-DEBUG SpiderMonkey library.
  */
 MOZ_BEGIN_EXTERN_C
 
 extern MFBT_API(void)
-JS_Assert(const char *s, const char *file, JSIntn ln);
+JS_Assert(const char *s, const char *file, int 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.
  */