Bug 514173 Make literal string buffers shareable r=dbaron,ehsan,bholley
authorNeil Rashbrook <neil@parkwaycc.co.uk>
Wed, 08 Jan 2014 20:51:38 +0000
changeset 178648 9db7cf4cc385e37495c0f484ac607b8daf31a238
parent 178647 5ebb4c3f51e828f1692070e39fa2bf94556545f8
child 178649 1a13c7459626faffb7b805b2189b5720c19bac65
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron, ehsan, bholley
bugs514173
milestone29.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
Bug 514173 Make literal string buffers shareable r=dbaron,ehsan,bholley
dom/indexedDB/ipc/IndexedDBParent.cpp
dom/indexedDB/ipc/IndexedDBParent.h
image/public/ImageLogging.h
ipc/glue/IPCMessageUtils.h
js/xpconnect/src/XPCString.cpp
js/xpconnect/src/xpcpublic.h
toolkit/components/downloads/nsDownloadManager.cpp
xpcom/io/nsLocalFileUnix.cpp
xpcom/string/public/moz.build
xpcom/string/public/nsAString.h
xpcom/string/public/nsLiteralString.h
xpcom/string/public/nsTLiteralString.h
xpcom/string/public/nsTSubstring.h
xpcom/string/public/string-template-def-char.h
xpcom/string/public/string-template-def-unichar.h
xpcom/string/public/string-template-undef.h
xpcom/string/src/nsTDependentString.cpp
xpcom/string/src/nsTPromiseFlatString.cpp
xpcom/string/src/nsTSubstring.cpp
--- a/dom/indexedDB/ipc/IndexedDBParent.cpp
+++ b/dom/indexedDB/ipc/IndexedDBParent.cpp
@@ -126,17 +126,17 @@ IndexedDBParent::CloneProtocol(Channel* 
   if (!actor || !contentParent->RecvPIndexedDBConstructor(actor)) {
     return nullptr;
   }
   return actor.forget();
 }
 
 bool
 IndexedDBParent::CheckPermissionInternal(const nsAString& aDatabaseName,
-                                         const nsDependentCString& aPermission)
+                                         const nsACString& aPermission)
 {
   MOZ_ASSERT(!mASCIIOrigin.IsEmpty());
   MOZ_ASSERT(mManagerContent || mManagerTab);
 
   if (mASCIIOrigin.EqualsLiteral(CHROME_ORIGIN)) {
     nsAutoCString fullPermission =
       NS_LITERAL_CSTRING(PERMISSION_PREFIX) +
       NS_ConvertUTF16toUTF8(aDatabaseName) +
--- a/dom/indexedDB/ipc/IndexedDBParent.h
+++ b/dom/indexedDB/ipc/IndexedDBParent.h
@@ -196,17 +196,17 @@ public:
 
   mozilla::ipc::IProtocol*
   CloneProtocol(Channel* aChannel,
                 mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
 
 protected:
   bool
   CheckPermissionInternal(const nsAString& aDatabaseName,
-                          const nsDependentCString& aPermission);
+                          const nsACString& aPermission);
 
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   virtual bool
   RecvPIndexedDBDatabaseConstructor(PIndexedDBDatabaseParent* aActor,
                                     const nsString& aName,
                                     const uint64_t& aVersion,
--- a/image/public/ImageLogging.h
+++ b/image/public/ImageLogging.h
@@ -24,182 +24,144 @@
 #if defined(PR_LOGGING)
 // Declared in imgRequest.cpp.
 extern PRLogModuleInfo *GetImgLog();
 
 #define GIVE_ME_MS_NOW() PR_IntervalToMilliseconds(PR_IntervalNow())
 
 class LogScope {
 public:
-  LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn) :
+  LogScope(PRLogModuleInfo *aLog, void *from, const char *fn) :
     mLog(aLog), mFrom(from), mFunc(fn)
   {
     PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s {ENTER}\n",
-                                   GIVE_ME_MS_NOW(),
-                                   mFrom, mFunc.get()));
+                                   GIVE_ME_MS_NOW(), mFrom, mFunc));
   }
 
   /* const char * constructor */
-  LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn,
-           const nsDependentCString &paramName, const char *paramValue) :
+  LogScope(PRLogModuleInfo *aLog, void *from, const char *fn,
+           const char *paramName, const char *paramValue) :
     mLog(aLog), mFrom(from), mFunc(fn)
   {
     PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%s\") {ENTER}\n",
-                                   GIVE_ME_MS_NOW(),
-                                   mFrom, mFunc.get(),
-                                   paramName.get(),
-                                   paramValue));
+                                   GIVE_ME_MS_NOW(), mFrom, mFunc,
+                                   paramName, paramValue));
   }
 
   /* void ptr constructor */
-  LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn,
-           const nsDependentCString &paramName, const void *paramValue) :
+  LogScope(PRLogModuleInfo *aLog, void *from, const char *fn,
+           const char *paramName, const void *paramValue) :
     mLog(aLog), mFrom(from), mFunc(fn)
   {
     PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=%p) {ENTER}\n",
-                                   GIVE_ME_MS_NOW(),
-                                   mFrom, mFunc.get(),
-                                   paramName.get(),
-                                   paramValue));
+                                   GIVE_ME_MS_NOW(), mFrom, mFunc,
+                                   paramName, paramValue));
   }
 
   /* int32_t constructor */
-  LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn,
-           const nsDependentCString &paramName, int32_t paramValue) :
+  LogScope(PRLogModuleInfo *aLog, void *from, const char *fn,
+           const char *paramName, int32_t paramValue) :
     mLog(aLog), mFrom(from), mFunc(fn)
   {
     PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%d\") {ENTER}\n",
-                                   GIVE_ME_MS_NOW(),
-                                   mFrom, mFunc.get(),
-                                   paramName.get(),
-                                   paramValue));
+                                   GIVE_ME_MS_NOW(), mFrom, mFunc,
+                                   paramName, paramValue));
   }
 
   /* uint32_t constructor */
-  LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn,
-           const nsDependentCString &paramName, uint32_t paramValue) :
+  LogScope(PRLogModuleInfo *aLog, void *from, const char *fn,
+           const char *paramName, uint32_t paramValue) :
     mLog(aLog), mFrom(from), mFunc(fn)
   {
     PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%d\") {ENTER}\n",
-                                   GIVE_ME_MS_NOW(),
-                                   mFrom, mFunc.get(),
-                                   paramName.get(),
-                                   paramValue));
+                                   GIVE_ME_MS_NOW(), mFrom, mFunc,
+                                   paramName, paramValue));
   }
 
 
   ~LogScope() {
     PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s {EXIT}\n",
-                                   GIVE_ME_MS_NOW(),
-                                   mFrom, mFunc.get()));
+                                   GIVE_ME_MS_NOW(), mFrom, mFunc));
   }
 
 private:
   PRLogModuleInfo *mLog;
   void *mFrom;
-  nsAutoCString mFunc;
+  const char *mFunc;
 };
 
 
 class LogFunc {
 public:
-  LogFunc(PRLogModuleInfo *aLog, void *from, const nsDependentCString &fn)
+  LogFunc(PRLogModuleInfo *aLog, void *from, const char *fn)
   {
     PR_LOG(aLog, PR_LOG_DEBUG, ("%d [this=%p] %s\n",
-                                GIVE_ME_MS_NOW(), from,
-                                fn.get()));
+                                GIVE_ME_MS_NOW(), from, fn));
   }
 
-  LogFunc(PRLogModuleInfo *aLog, void *from, const nsDependentCString &fn,
-          const nsDependentCString &paramName, const char *paramValue)
+  LogFunc(PRLogModuleInfo *aLog, void *from, const char *fn,
+          const char *paramName, const char *paramValue)
   {
     PR_LOG(aLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%s\")\n",
-                                GIVE_ME_MS_NOW(), from,
-                                fn.get(),
-                                paramName.get(), paramValue));
+                                GIVE_ME_MS_NOW(), from, fn,
+                                paramName, paramValue));
   }
 
-  LogFunc(PRLogModuleInfo *aLog, void *from, const nsDependentCString &fn,
-          const nsDependentCString &paramName, const void *paramValue)
+  LogFunc(PRLogModuleInfo *aLog, void *from, const char *fn,
+          const char *paramName, const void *paramValue)
   {
     PR_LOG(aLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%p\")\n",
-                                GIVE_ME_MS_NOW(), from,
-                                fn.get(),
-                                paramName.get(), paramValue));
+                                GIVE_ME_MS_NOW(), from, fn,
+                                paramName, paramValue));
   }
 
 
-  LogFunc(PRLogModuleInfo *aLog, void *from, const nsDependentCString &fn,
-          const nsDependentCString &paramName, uint32_t paramValue)
+  LogFunc(PRLogModuleInfo *aLog, void *from, const char *fn,
+          const char *paramName, uint32_t paramValue)
   {
     PR_LOG(aLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%d\")\n",
                                 GIVE_ME_MS_NOW(), from,
-                                fn.get(),
-                                paramName.get(), paramValue));
+                                fn,
+                                paramName, paramValue));
   }
 
 };
 
 
 class LogMessage {
 public:
-  LogMessage(PRLogModuleInfo *aLog, void *from, const nsDependentCString &fn,
-             const nsDependentCString &msg)
+  LogMessage(PRLogModuleInfo *aLog, void *from, const char *fn,
+             const char *msg)
   {
     PR_LOG(aLog, PR_LOG_DEBUG, ("%d [this=%p] %s -- %s\n",
-                                GIVE_ME_MS_NOW(), from,
-                                fn.get(),
-                                msg.get()));
+                                GIVE_ME_MS_NOW(), from, fn, msg));
   }
 };
 
 #define LOG_SCOPE_APPEND_LINE_NUMBER_PASTE(id, line) id ## line
 #define LOG_SCOPE_APPEND_LINE_NUMBER_EXPAND(id, line) LOG_SCOPE_APPEND_LINE_NUMBER_PASTE(id, line)
 #define LOG_SCOPE_APPEND_LINE_NUMBER(id) LOG_SCOPE_APPEND_LINE_NUMBER_EXPAND(id, __LINE__)
 
 #define LOG_SCOPE(l, s) \
-  LogScope LOG_SCOPE_APPEND_LINE_NUMBER(LOG_SCOPE_TMP_VAR) (l,                            \
-                                                            static_cast<void *>(this),    \
-                                                            NS_LITERAL_CSTRING(s))
+  LogScope LOG_SCOPE_APPEND_LINE_NUMBER(LOG_SCOPE_TMP_VAR) (l, this, s)
 
 #define LOG_SCOPE_WITH_PARAM(l, s, pn, pv) \
-  LogScope LOG_SCOPE_APPEND_LINE_NUMBER(LOG_SCOPE_TMP_VAR) (l,                            \
-                                                            static_cast<void *>(this),    \
-                                                            NS_LITERAL_CSTRING(s),        \
-                                                            NS_LITERAL_CSTRING(pn), pv)
+  LogScope LOG_SCOPE_APPEND_LINE_NUMBER(LOG_SCOPE_TMP_VAR) (l, this, s, pn, pv)
 
-#define LOG_FUNC(l, s)                  \
-  LogFunc(l,                            \
-          static_cast<void *>(this),    \
-          NS_LITERAL_CSTRING(s))
+#define LOG_FUNC(l, s) LogFunc(l, this, s)
 
-#define LOG_FUNC_WITH_PARAM(l, s, pn, pv) \
-  LogFunc(l,                              \
-          static_cast<void *>(this),      \
-          NS_LITERAL_CSTRING(s),          \
-          NS_LITERAL_CSTRING(pn), pv)
+#define LOG_FUNC_WITH_PARAM(l, s, pn, pv) LogFunc(l, this, s, pn, pv)
 
-#define LOG_STATIC_FUNC(l, s)           \
-  LogFunc(l,                            \
-          nullptr,                       \
-          NS_LITERAL_CSTRING(s))
+#define LOG_STATIC_FUNC(l, s) LogFunc(l, nullptr, s)
 
-#define LOG_STATIC_FUNC_WITH_PARAM(l, s, pn, pv) \
-  LogFunc(l,                             \
-          nullptr,                        \
-          NS_LITERAL_CSTRING(s),         \
-          NS_LITERAL_CSTRING(pn), pv)
+#define LOG_STATIC_FUNC_WITH_PARAM(l, s, pn, pv) LogFunc(l, nullptr, s, pn, pv)
 
 
 
-#define LOG_MSG(l, s, m)                   \
-  LogMessage(l,                            \
-             static_cast<void *>(this),    \
-             NS_LITERAL_CSTRING(s),        \
-             NS_LITERAL_CSTRING(m))
+#define LOG_MSG(l, s, m) LogMessage(l, this, s, m)
 
 #else
 
 #define LOG_SCOPE(l, s)
 #define LOG_SCOPE_WITH_PARAM(l, s, pn, pv)
 #define LOG_FUNC(l, s)
 #define LOG_FUNC_WITH_PARAM(l, s, pn, pv)
 #define LOG_STATIC_FUNC(l, s)
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -309,32 +309,44 @@ struct ParamTraits<nsAString>
 };
 
 template <>
 struct ParamTraits<nsCString> : ParamTraits<nsACString>
 {
   typedef nsCString paramType;
 };
 
+template <>
+struct ParamTraits<nsLiteralCString> : ParamTraits<nsACString>
+{
+  typedef nsLiteralCString paramType;
+};
+
 #ifdef MOZILLA_INTERNAL_API
 
 template<>
 struct ParamTraits<nsAutoCString> : ParamTraits<nsCString>
 {
   typedef nsAutoCString paramType;
 };
 
 #endif  // MOZILLA_INTERNAL_API
 
 template <>
 struct ParamTraits<nsString> : ParamTraits<nsAString>
 {
   typedef nsString paramType;
 };
 
+template <>
+struct ParamTraits<nsLiteralString> : ParamTraits<nsAString>
+{
+  typedef nsLiteralString paramType;
+};
+
 template <typename E>
 struct ParamTraits<FallibleTArray<E> >
 {
   typedef FallibleTArray<E> paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     uint32_t length = aParam.Length();
--- a/js/xpconnect/src/XPCString.cpp
+++ b/js/xpconnect/src/XPCString.cpp
@@ -44,16 +44,25 @@ XPCStringConvert::ClearZoneCache(JS::Zon
     if (cache) {
         cache->mBuffer = nullptr;
         cache->mString = nullptr;
     }
 }
 
 // static
 void
+XPCStringConvert::FinalizeLiteral(const JSStringFinalizer *fin, jschar *chars)
+{
+}
+
+const JSStringFinalizer XPCStringConvert::sLiteralFinalizer =
+    { XPCStringConvert::FinalizeLiteral };
+
+// static
+void
 XPCStringConvert::FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars)
 {
     nsStringBuffer* buf = nsStringBuffer::FromData(chars);
     buf->Release();
 }
 
 const JSStringFinalizer XPCStringConvert::sDOMStringFinalizer =
     { XPCStringConvert::FinalizeDOMString };
@@ -69,16 +78,26 @@ XPCStringConvert::ReadableToJSVal(JSCont
     *sharedBuffer = nullptr;
 
     uint32_t length = readable.Length();
     if (length == 0) {
         vp.set(JS_GetEmptyStringValue(cx));
         return true;
     }
 
+    if (readable.IsLiteral()) {
+        JSString *str = JS_NewExternalString(cx,
+                                             static_cast<const jschar*>(readable.BeginReading()),
+                                             length, &sLiteralFinalizer);
+        if (!str)
+            return false;
+        vp.setString(str);
+        return true;
+    }
+
     nsStringBuffer *buf = nsStringBuffer::FromString(readable);
     if (buf) {
         bool shared;
         if (!StringBufferToJSVal(cx, buf, length, vp, &shared))
             return false;
         if (shared)
             *sharedBuffer = buf;
         return true;
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -233,17 +233,19 @@ public:
         *sharedBuffer = true;
         return true;
     }
 
     static void FreeZoneCache(JS::Zone *zone);
     static void ClearZoneCache(JS::Zone *zone);
 
 private:
-    static const JSStringFinalizer sDOMStringFinalizer;
+    static const JSStringFinalizer sLiteralFinalizer, sDOMStringFinalizer;
+
+    static void FinalizeLiteral(const JSStringFinalizer *fin, jschar *chars);
 
     static void FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars);
 
     XPCStringConvert();         // not implemented
 };
 
 namespace xpc {
 
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -1088,17 +1088,17 @@ nsDownloadManager::GetQuitBehavior()
 // could be found, either private or public.
 
 nsresult
 nsDownloadManager::GetDownloadFromDB(const nsACString& aGUID, nsDownload **retVal)
 {
   MOZ_ASSERT(!FindDownload(aGUID),
              "If it is a current download, you should not call this method!");
 
-  nsDependentCString query = NS_LITERAL_CSTRING(
+  NS_NAMED_LITERAL_CSTRING(query,
     "SELECT id, state, startTime, source, target, tempPath, name, referrer, "
            "entityID, currBytes, maxBytes, mimeType, preferredAction, "
            "preferredApplication, autoResume, guid "
     "FROM moz_downloads "
     "WHERE guid = :guid");
   // First, let's query the database and see if it even exists
   nsCOMPtr<mozIStorageStatement> stmt;
   nsresult rv = mDBConn->CreateStatement(query, getter_AddRefs(stmt));
--- a/xpcom/io/nsLocalFileUnix.cpp
+++ b/xpcom/io/nsLocalFileUnix.cpp
@@ -1887,18 +1887,17 @@ nsLocalFile::Launch()
 #elif defined(MOZ_WIDGET_ANDROID)
     // Try to get a mimetype, if this fails just use the file uri alone
     nsresult rv;
     nsAutoCString type;
     nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1", &rv));
     if (NS_SUCCEEDED(rv))
         rv = mimeService->GetTypeFromFile(this, type);
 
-    nsDependentCString fileUri = NS_LITERAL_CSTRING("file://");
-    fileUri.Append(mPath);
+    nsAutoCString fileUri = NS_LITERAL_CSTRING("file://") + mPath;
     return GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(fileUri), NS_ConvertUTF8toUTF16(type)) ? NS_OK : NS_ERROR_FAILURE;
 #elif defined(MOZ_WIDGET_COCOA)
     CFURLRef url;
     if (NS_SUCCEEDED(GetCFURL(&url))) {
         nsresult rv = CocoaFileUtils::OpenURL(url);
         ::CFRelease(url);
         return rv;
     }
--- a/xpcom/string/public/moz.build
+++ b/xpcom/string/public/moz.build
@@ -18,16 +18,17 @@ EXPORTS += [
     'nsString.h',
     'nsStringBuffer.h',
     'nsStringFwd.h',
     'nsStringIterator.h',
     'nsSubstring.h',
     'nsSubstringTuple.h',
     'nsTDependentString.h',
     'nsTDependentSubstring.h',
+    'nsTLiteralString.h',
     'nsTPromiseFlatString.h',
     'nsTString.h',
     'nsTSubstring.h',
     'nsTSubstringTuple.h',
     'nsUTF8Utils.h',
     'nsXPCOMStrings.h',
     'nsXPIDLString.h',
     'string-template-def-char.h',
--- a/xpcom/string/public/nsAString.h
+++ b/xpcom/string/public/nsAString.h
@@ -11,24 +11,16 @@
 #ifndef nsStringFwd_h___
 #include "nsStringFwd.h"
 #endif
 
 #ifndef nsStringIterator_h___
 #include "nsStringIterator.h"
 #endif
 
-// If some platform(s) can't handle our template that matches literal strings,
-// then we'll disable it on those platforms.
-#ifndef NS_DISABLE_LITERAL_TEMPLATE
-#  if (defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x560)) || (defined(__HP_aCC) && (__HP_aCC <= 012100))
-#    define NS_DISABLE_LITERAL_TEMPLATE
-#  endif
-#endif /* !NS_DISABLE_LITERAL_TEMPLATE */
-
 #include <string.h>
 #include <stdarg.h>
 
 #include "mozilla/fallible.h"
 
 #define kNotFound -1
 
   // declare nsAString
--- a/xpcom/string/public/nsLiteralString.h
+++ b/xpcom/string/public/nsLiteralString.h
@@ -5,51 +5,37 @@
 
 #ifndef nsLiteralString_h___
 #define nsLiteralString_h___
 
 #ifndef nscore_h___
 #include "nscore.h"
 #endif
 
-#ifndef nsDependentString_h___
-#include "nsDependentString.h"
+#ifndef nsString_h___
+#include "nsString.h"
 #endif
 
+  // declare nsLiteralString
+#include "string-template-def-unichar.h"
+#include "nsTLiteralString.h"
+#include "string-template-undef.h"
+
+  // declare nsLiteralCString
+#include "string-template-def-char.h"
+#include "nsTLiteralString.h"
+#include "string-template-undef.h"
+
 #include "mozilla/Char16.h"
 
-namespace mozilla {
-namespace internal {
-
-// This is the same as sizeof(c) - 1, except it won't compile if c isn't a
-// string literal.  This ensures that NS_LITERAL_CSTRING doesn't compile if you
-// pass it a char* (or something else for that matter).
-template<int n>
-inline uint32_t LiteralStringLength(const char (&c)[n])
-{
-  return n - 1;
-}
-
-template<int n>
-inline uint32_t LiteralWStringLength(const char16_t (&c)[n])
-{
-  return n - 1;
-}
+#define NS_MULTILINE_LITERAL_STRING(s)            static_cast<const nsLiteralString&>(nsLiteralString(s))
+#define NS_MULTILINE_LITERAL_STRING_INIT(n,s)     n(s)
+#define NS_NAMED_MULTILINE_LITERAL_STRING(n,s)    const nsLiteralString n(s)
 
-} // namespace internal
-} // namespace mozilla
-
-#define NS_MULTILINE_LITERAL_STRING(s)          nsDependentString(reinterpret_cast<const nsAString::char_type*>(s), mozilla::internal::LiteralWStringLength(s))
-#define NS_MULTILINE_LITERAL_STRING_INIT(n,s)   n(reinterpret_cast<const nsAString::char_type*>(s), mozilla::internal::LiteralWStringLength(s))
-#define NS_NAMED_MULTILINE_LITERAL_STRING(n,s)  const nsDependentString n(reinterpret_cast<const nsAString::char_type*>(s), mozilla::internal::LiteralWStringLength(s))
-typedef nsDependentString nsLiteralString;
+#define NS_LITERAL_STRING(s)                      static_cast<const nsLiteralString&>(nsLiteralString(MOZ_UTF16(s)))
+#define NS_LITERAL_STRING_INIT(n,s)               n(MOZ_UTF16(s))
+#define NS_NAMED_LITERAL_STRING(n,s)              const nsLiteralString n(MOZ_UTF16(s))
 
-#define NS_LITERAL_STRING(s)                      static_cast<const nsAFlatString&>(NS_MULTILINE_LITERAL_STRING(MOZ_UTF16(s)))
-#define NS_LITERAL_STRING_INIT(n,s)               NS_MULTILINE_LITERAL_STRING_INIT(n, MOZ_UTF16(s))
-#define NS_NAMED_LITERAL_STRING(n,s)              NS_NAMED_MULTILINE_LITERAL_STRING(n, MOZ_UTF16(s))
-
-#define NS_LITERAL_CSTRING(s)                     static_cast<const nsDependentCString&>(nsDependentCString(s, mozilla::internal::LiteralStringLength(s)))
-#define NS_LITERAL_CSTRING_INIT(n,s)              n(s, mozilla::internal::LiteralStringLength(s))
-#define NS_NAMED_LITERAL_CSTRING(n,s)             const nsDependentCString n(s, mozilla::internal::LiteralStringLength(s))
-
-typedef nsDependentCString nsLiteralCString;
+#define NS_LITERAL_CSTRING(s)                     static_cast<const nsLiteralCString&>(nsLiteralCString(s))
+#define NS_LITERAL_CSTRING_INIT(n,s)              n(s)
+#define NS_NAMED_LITERAL_CSTRING(n,s)             const nsLiteralCString n(s)
 
 #endif /* !defined(nsLiteralString_h___) */
new file mode 100644
--- /dev/null
+++ b/xpcom/string/public/nsTLiteralString.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+
+  /**
+   * nsTLiteralString_CharT
+   *
+   * Stores a null-terminated, immutable sequence of characters.
+   *
+   * Subclass of nsTString that restricts string value to a literal
+   * character sequence.  This class does not own its data. The data is
+   * assumed to be permanent. In practice this is true because this code
+   * is only usable by and for libxul.
+   */
+class nsTLiteralString_CharT : public nsTString_CharT
+  {
+    public:
+
+      typedef nsTLiteralString_CharT    self_type;
+
+    public:
+
+        /**
+         * constructor
+         */
+
+      template<size_type N>
+      nsTLiteralString_CharT( const char_type (&str)[N] )
+        : string_type(const_cast<char_type*>(str), N - 1, F_TERMINATED | F_LITERAL)
+        {
+        }
+
+    private:
+
+        // NOT TO BE IMPLEMENTED
+      template<size_type N>
+      nsTLiteralString_CharT( char_type (&str)[N] ) MOZ_DELETE;
+  };
--- a/xpcom/string/public/nsTSubstring.h
+++ b/xpcom/string/public/nsTSubstring.h
@@ -209,21 +209,31 @@ class nsTSubstring_CharT
           return mData;
         }
 
       size_type Length() const
         {
           return mLength;
         }
 
+      uint32_t Flags() const
+        {
+          return mFlags;
+        }
+
       bool IsEmpty() const
         {
           return mLength == 0;
         }
 
+      bool IsLiteral() const
+        {
+          return (mFlags & F_LITERAL) != 0;
+        }
+
       bool IsVoid() const
         {
           return (mFlags & F_VOIDED) != 0;
         }
 
       bool IsTerminated() const
         {
           return (mFlags & F_TERMINATED) != 0;
@@ -292,67 +302,41 @@ class nsTSubstring_CharT
       bool NS_FASTCALL EqualsASCII( const char* data ) const;
 
     // EqualsLiteral must ONLY be applied to an actual literal string, or
     // a char array *constant* declared without an explicit size.
     // Do not attempt to use it with a regular char* pointer, or with a
     // non-constant char array variable. Use EqualsASCII for them.
     // The template trick to acquire the array length at compile time without
     // using a macro is due to Corey Kosak, with much thanks.
-#ifdef NS_DISABLE_LITERAL_TEMPLATE
-      inline bool EqualsLiteral( const char* str ) const
-        {
-          return EqualsASCII(str);
-        }
-#else
       template<int N>
       inline bool EqualsLiteral( const char (&str)[N] ) const
         {
           return EqualsASCII(str, N-1);
         }
-      template<int N>
-      inline bool EqualsLiteral( char (&str)[N] ) const
-        {
-          const char* s = str;
-          return EqualsASCII(s, N-1);
-        }
-#endif
 
     // The LowerCaseEquals methods compare the ASCII-lowercase version of
     // this string (lowercasing only ASCII uppercase characters) to some
     // ASCII/Literal string. The ASCII string is *not* lowercased for
     // you. If you compare to an ASCII or literal string that contains an
     // uppercase character, it is guaranteed to return false. We will
     // throw assertions too.
       bool NS_FASTCALL LowerCaseEqualsASCII( const char* data, size_type len ) const;
       bool NS_FASTCALL LowerCaseEqualsASCII( const char* data ) const;
 
     // LowerCaseEqualsLiteral must ONLY be applied to an actual
     // literal string, or a char array *constant* declared without an 
     // explicit size.  Do not attempt to use it with a regular char*
     // pointer, or with a non-constant char array variable. Use
     // LowerCaseEqualsASCII for them.
-#ifdef NS_DISABLE_LITERAL_TEMPLATE
-      inline bool LowerCaseEqualsLiteral( const char* str ) const
-        {
-          return LowerCaseEqualsASCII(str);
-        }
-#else
       template<int N>
       inline bool LowerCaseEqualsLiteral( const char (&str)[N] ) const
         {
           return LowerCaseEqualsASCII(str, N-1);
         }
-      template<int N>
-      inline bool LowerCaseEqualsLiteral( char (&str)[N] ) const
-        {
-          const char* s = str;
-          return LowerCaseEqualsASCII(s, N-1);
-        }
-#endif
 
         /**
          * assignment
          */
 
       void NS_FASTCALL Assign( char_type c );
       bool NS_FASTCALL Assign( char_type c, const fallible_t& ) NS_WARN_UNUSED_RESULT;
 
@@ -401,26 +385,23 @@ class nsTSubstring_CharT
         }
 
     // AssignLiteral must ONLY be applied to an actual literal string, or
     // a char array *constant* declared without an explicit size.
     // Do not attempt to use it with a regular char* pointer, or with a 
     // non-constant char array variable. Use AssignASCII for those.
     // There are not fallible version of these methods because they only really
     // apply to small allocations that we wouldn't want to check anyway.
-#ifdef NS_DISABLE_LITERAL_TEMPLATE
-      void AssignLiteral( const char* str )
-                  { AssignASCII(str); }
-#else
+      template<int N>
+      void AssignLiteral( const char_type (&str)[N] )
+                  { AssignLiteral(str, N - 1); }
+#ifdef CharT_is_PRUnichar
       template<int N>
       void AssignLiteral( const char (&str)[N] )
                   { AssignASCII(str, N-1); }
-      template<int N>
-      void AssignLiteral( char (&str)[N] )
-                  { AssignASCII(str, N-1); }
 #endif
 
       self_type& operator=( char_type c )                                                       { Assign(c);        return *this; }
       self_type& operator=( const char_type* data )                                             { Assign(data);     return *this; }
 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
       self_type& operator=( char16ptr_t data )                                                  { Assign(data);     return *this; }
 #endif
       self_type& operator=( const self_type& str )                                              { Assign(str);      return *this; }
@@ -435,16 +416,22 @@ class nsTSubstring_CharT
 
       void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, char_type c );
       void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) );
       void Replace( index_type cutStart, size_type cutLength, const self_type& str )      { Replace(cutStart, cutLength, str.Data(), str.Length()); }
       void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple );
 
       void NS_FASTCALL ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length = size_type(-1) );
 
+    // ReplaceLiteral must ONLY be applied to an actual literal string.
+    // Do not attempt to use it with a regular char* pointer, or with a char
+    // array variable. Use Replace or ReplaceASCII for those.
+      template<int N>
+      void ReplaceLiteral( index_type cutStart, size_type cutLength, const char_type (&str)[N] ) { ReplaceLiteral(cutStart, cutLength, str, N - 1); }
+
       void Append( char_type c )                                                                 { Replace(mLength, 0, c); }
       void Append( const char_type* data, size_type length = size_type(-1) )                     { Replace(mLength, 0, data, length); }
 
 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
     void Append( char16ptr_t data, size_type length = size_type(-1) )                            { Append(static_cast<const char16_t*>(data), length); }
 #endif
 
       void Append( const self_type& str )                                                        { Replace(mLength, 0, str); }
@@ -491,27 +478,23 @@ class nsTSubstring_CharT
        * Append the given float to this string 
        */
       void NS_FASTCALL AppendFloat( float aFloat );
       void NS_FASTCALL AppendFloat( double aFloat );
   public:
 
     // AppendLiteral must ONLY be applied to an actual literal string.
     // Do not attempt to use it with a regular char* pointer, or with a char
-    // array variable. Use AppendASCII for those.
-#ifdef NS_DISABLE_LITERAL_TEMPLATE
-      void AppendLiteral( const char* str )
-                  { AppendASCII(str); }
-#else
+    // array variable. Use Append or AppendASCII for those.
+      template<int N>
+      void AppendLiteral( const char_type (&str)[N] )                                             { ReplaceLiteral(mLength, 0, str, N - 1); }
+#ifdef CharT_is_PRUnichar
       template<int N>
       void AppendLiteral( const char (&str)[N] )
                   { AppendASCII(str, N-1); }
-      template<int N>
-      void AppendLiteral( char (&str)[N] )
-                  { AppendASCII(str, N-1); }
 #endif
 
       self_type& operator+=( char_type c )                                                       { Append(c);        return *this; }
       self_type& operator+=( const char_type* data )                                             { Append(data);     return *this; }
 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
       self_type& operator+=( char16ptr_t data )                                                  { Append(data);     return *this; }
 #endif
       self_type& operator+=( const self_type& str )                                              { Append(str);      return *this; }
@@ -521,16 +504,22 @@ class nsTSubstring_CharT
       void Insert( const char_type* data, index_type pos, size_type length = size_type(-1) )     { Replace(pos, 0, data, length); }
 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
       void Insert( char16ptr_t data, index_type pos, size_type length = size_type(-1) )
         { Insert(static_cast<const char16_t*>(data), pos, length); }
 #endif
       void Insert( const self_type& str, index_type pos )                                        { Replace(pos, 0, str); }
       void Insert( const substring_tuple_type& tuple, index_type pos )                           { Replace(pos, 0, tuple); }
 
+    // InsertLiteral must ONLY be applied to an actual literal string.
+    // Do not attempt to use it with a regular char* pointer, or with a char
+    // array variable. Use Insert for those.
+      template<int N>
+      void InsertLiteral( const char_type (&str)[N], index_type pos )                            { ReplaceLiteral(pos, 0, str, N - 1); }
+
       void Cut( index_type cutStart, size_type cutLength )                                       { Replace(cutStart, cutLength, char_traits::sEmptyBuffer, 0); }
 
 
         /**
          * buffer sizing
          */
 
         /**
@@ -840,16 +829,19 @@ class nsTSubstring_CharT
          * this helper function stores the specified dataFlags in mFlags
          */
       void SetDataFlags(uint32_t dataFlags)
         {
           NS_ASSERTION((dataFlags & 0xFFFF0000) == 0, "bad flags");
           mFlags = dataFlags | (mFlags & 0xFFFF0000);
         }
 
+      void NS_FASTCALL AssignLiteral( const char_type* data, size_type length );
+      void NS_FASTCALL ReplaceLiteral( index_type cutStart, size_type cutLength, const char_type* data, size_type length );
+
       static int AppendFunc( void* arg, const char* s, uint32_t len);
 
     public:
 
       // mFlags is a bitwise combination of the following flags.  the meaning
       // and interpretation of these flags is an implementation detail.
       // 
       // NOTE: these flags are declared public _only_ for convenience inside
@@ -860,16 +852,17 @@ class nsTSubstring_CharT
           F_NONE         = 0,       // no flags
 
           // data flags are in the lower 16-bits
           F_TERMINATED   = 1 << 0,  // IsTerminated returns true
           F_VOIDED       = 1 << 1,  // IsVoid returns true
           F_SHARED       = 1 << 2,  // mData points to a heap-allocated, shared buffer
           F_OWNED        = 1 << 3,  // mData points to a heap-allocated, raw buffer
           F_FIXED        = 1 << 4,  // mData points to a fixed-size writable, dependent buffer
+          F_LITERAL      = 1 << 5,  // mData points to a string literal; F_TERMINATED will also be set
 
           // class flags are in the upper 16-bits
           F_CLASS_FIXED  = 1 << 16   // indicates that |this| is of type nsTFixedString
         };
 
       //
       // Some terminology:
       //
--- a/xpcom/string/public/string-template-def-char.h
+++ b/xpcom/string/public/string-template-def-char.h
@@ -12,13 +12,14 @@
 #define nsTFixedString_CharT                nsFixedCString
 #define nsTAutoString_CharT                 nsAutoCString
 #define nsTSubstring_CharT                  nsACString
 #define nsTSubstringTuple_CharT             nsCSubstringTuple
 #define nsTStringComparator_CharT           nsCStringComparator
 #define nsTDefaultStringComparator_CharT    nsDefaultCStringComparator
 #define nsTDependentString_CharT            nsDependentCString
 #define nsTDependentSubstring_CharT         nsDependentCSubstring
+#define nsTLiteralString_CharT              nsLiteralCString
 #define nsTXPIDLString_CharT                nsXPIDLCString
 #define nsTGetterCopies_CharT               nsCGetterCopies
 #define nsTAdoptingString_CharT             nsAdoptingCString
 #define nsTPromiseFlatString_CharT          nsPromiseFlatCString
 #define TPromiseFlatString_CharT            PromiseFlatCString
--- a/xpcom/string/public/string-template-def-unichar.h
+++ b/xpcom/string/public/string-template-def-unichar.h
@@ -12,13 +12,14 @@
 #define nsTFixedString_CharT                nsFixedString
 #define nsTAutoString_CharT                 nsAutoString
 #define nsTSubstring_CharT                  nsAString
 #define nsTSubstringTuple_CharT             nsSubstringTuple
 #define nsTStringComparator_CharT           nsStringComparator
 #define nsTDefaultStringComparator_CharT    nsDefaultStringComparator
 #define nsTDependentString_CharT            nsDependentString
 #define nsTDependentSubstring_CharT         nsDependentSubstring
+#define nsTLiteralString_CharT              nsLiteralString
 #define nsTXPIDLString_CharT                nsXPIDLString
 #define nsTGetterCopies_CharT               nsGetterCopies
 #define nsTAdoptingString_CharT             nsAdoptingString
 #define nsTPromiseFlatString_CharT          nsPromiseFlatString
 #define TPromiseFlatString_CharT            PromiseFlatString
--- a/xpcom/string/public/string-template-undef.h
+++ b/xpcom/string/public/string-template-undef.h
@@ -13,13 +13,14 @@
 #undef nsTFixedString_CharT
 #undef nsTAutoString_CharT
 #undef nsTSubstring_CharT
 #undef nsTSubstringTuple_CharT
 #undef nsTStringComparator_CharT
 #undef nsTDefaultStringComparator_CharT
 #undef nsTDependentString_CharT
 #undef nsTDependentSubstring_CharT
+#undef nsTLiteralString_CharT
 #undef nsTXPIDLString_CharT
 #undef nsTGetterCopies_CharT
 #undef nsTAdoptingString_CharT
 #undef nsTPromiseFlatString_CharT
 #undef TPromiseFlatString_CharT
--- a/xpcom/string/src/nsTDependentString.cpp
+++ b/xpcom/string/src/nsTDependentString.cpp
@@ -2,21 +2,23 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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/. */
 
 void
 nsTDependentString_CharT::Rebind( const string_type& str, uint32_t startPos )
   {
+    NS_ABORT_IF_FALSE(str.Flags() & F_TERMINATED, "Unterminated flat string");
+
     // If we currently own a buffer, release it.
     Finalize();
 
     size_type strLength = str.Length();
 
     if (startPos > strLength)
       startPos = strLength;
 
     mData = const_cast<char_type*>(static_cast<const char_type*>(str.Data())) + startPos;
     mLength = strLength - startPos;
 
-    SetDataFlags(F_TERMINATED);
+    SetDataFlags(str.Flags() & (F_TERMINATED | F_LITERAL));
   }
--- a/xpcom/string/src/nsTPromiseFlatString.cpp
+++ b/xpcom/string/src/nsTPromiseFlatString.cpp
@@ -6,15 +6,16 @@
 
 void
 nsTPromiseFlatString_CharT::Init(const substring_type& str)
   {
     if (str.IsTerminated())
       {
         mData = const_cast<char_type*>(static_cast<const char_type*>(str.Data()));
         mLength = str.Length();
-        mFlags = F_TERMINATED; // does not promote F_VOIDED
+        mFlags = str.mFlags & (F_TERMINATED | F_LITERAL);
+                 // does not promote F_VOIDED
       }
     else
       {
         Assign(str);
       }
   }
--- a/xpcom/string/src/nsTSubstring.cpp
+++ b/xpcom/string/src/nsTSubstring.cpp
@@ -347,16 +347,25 @@ nsTSubstring_CharT::AssignASCII( const c
     if (!ReplacePrep(0, mLength, length))
       return false;
 
     char_traits::copyASCII(mData, data, length);
     return true;
   }
 
 void
+nsTSubstring_CharT::AssignLiteral( const char_type* data, size_type length )
+  {
+    ::ReleaseData(mData, mFlags);
+    mData = const_cast<char_type*>(data);
+    mLength = length;
+    SetDataFlags(F_TERMINATED | F_LITERAL);
+  }
+
+void
 nsTSubstring_CharT::Assign( const self_type& str )
 {
   if (!Assign(str, fallible_t()))
     NS_ABORT_OOM(str.Length());
 }
 
 bool
 nsTSubstring_CharT::Assign( const self_type& str, const fallible_t& )
@@ -386,16 +395,23 @@ nsTSubstring_CharT::Assign( const self_t
         mData = str.mData;
         mLength = str.mLength;
         SetDataFlags(F_TERMINATED | F_SHARED);
 
         // get an owning reference to the mData
         nsStringBuffer::FromData(mData)->AddRef();
         return true;
       }
+    else if (str.mFlags & F_LITERAL)
+      {
+        NS_ABORT_IF_FALSE(str.mFlags & F_TERMINATED, "Unterminated literal");
+
+        AssignLiteral(str.mData, str.mLength);
+        return true;
+      }
 
     // else, treat this like an ordinary assignment.
     return Assign(str.Data(), str.Length(), fallible_t());
   }
 
 void
 nsTSubstring_CharT::Assign( const substring_tuple_type& tuple )
   {
@@ -532,16 +548,27 @@ nsTSubstring_CharT::Replace( index_type 
 
     cutStart = XPCOM_MIN(cutStart, Length());
 
     if (ReplacePrep(cutStart, cutLength, length) && length > 0)
       tuple.WriteTo(mData + cutStart, length);
   }
 
 void
+nsTSubstring_CharT::ReplaceLiteral( index_type cutStart, size_type cutLength, const char_type* data, size_type length )
+  {
+    cutStart = XPCOM_MIN(cutStart, Length());
+
+    if (!cutStart && cutLength == Length())
+      AssignLiteral(data, length);
+    else if (ReplacePrep(cutStart, cutLength, length) && length > 0)
+      char_traits::copy(mData + cutStart, data, length);
+  }
+
+void
 nsTSubstring_CharT::SetCapacity( size_type capacity )
   {
     if (!SetCapacity(capacity, fallible_t()))
       NS_ABORT_OOM(capacity);
   }
 
 bool
 nsTSubstring_CharT::SetCapacity( size_type capacity, const fallible_t& )