Backed out changeset 966836866e8a (bug 1425807) for Build Bustage. r=backout on a CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Tue, 19 Dec 2017 03:09:04 +0200
changeset 396791 ce813e8a46832f31a3c696880a8554e63b923fb8
parent 396790 095928b49caa8918ac6354044100ed3be6c0b9f6
child 396792 31c635f8f249de38c1378ac0b88ea091c13134f5
push id33111
push userdluca@mozilla.com
push dateTue, 19 Dec 2017 10:06:26 +0000
treeherdermozilla-central@c76ff8b1c4d4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1425807
milestone59.0a1
backs out966836866e8afe423a01a9926834a26cb3d3e2b0
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
Backed out changeset 966836866e8a (bug 1425807) for Build Bustage. r=backout on a CLOSED TREE
netwerk/dns/nsDNSService2.cpp
netwerk/dns/nsHostResolver.cpp
netwerk/dns/nsHostResolver.h
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -83,26 +83,28 @@ NS_IMPL_ISUPPORTS(nsDNSRecord, nsIDNSRec
 
 NS_IMETHODIMP
 nsDNSRecord::GetCanonicalName(nsACString &result)
 {
     // this method should only be called if we have a CNAME
     NS_ENSURE_TRUE(mHostRecord->flags & nsHostResolver::RES_CANON_NAME,
                    NS_ERROR_NOT_AVAILABLE);
 
-    MutexAutoLock lock(mHostRecord->addr_info_lock);
-    if (mHostRecord->addr_info) {
-        const char* cname = mHostRecord->addr_info->mCanonicalName ?
-            mHostRecord->addr_info->mCanonicalName :
-            mHostRecord->addr_info->mHostName;
+    // if the record is for an IP address literal, then the canonical
+    // host name is the IP address literal.
+    const char *cname;
+    {
+        MutexAutoLock lock(mHostRecord->addr_info_lock);
+        if (mHostRecord->addr_info)
+            cname = mHostRecord->addr_info->mCanonicalName ?
+                mHostRecord->addr_info->mCanonicalName :
+                mHostRecord->addr_info->mHostName;
+        else
+            cname = mHostRecord->host;
         result.Assign(cname);
-    } else {
-        // if the record is for an IP address literal, then the canonical
-        // host name is the IP address literal.
-        result = mHostRecord->host;
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
 {
     if (mDone) {
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -157,60 +157,57 @@ IsLowPriority(uint16_t flags)
 }
 
 //----------------------------------------------------------------------------
 // this macro filters out any flags that are not used when constructing the
 // host key.  the significant flags are those that would affect the resulting
 // host record (i.e., the flags that are passed down to PR_GetAddrInfoByName).
 #define RES_KEY_FLAGS(_f) ((_f) & nsHostResolver::RES_CANON_NAME)
 
-bool
-nsHostKey::operator==(const nsHostKey& other) const
-{
-    return host == other.host &&
-        RES_KEY_FLAGS (flags) == RES_KEY_FLAGS(other.flags) &&
-        af == other.af &&
-        netInterface == other.netInterface &&
-        originSuffix == other.originSuffix;
-}
-
-size_t
-nsHostKey::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
-{
-    size_t n = 0;
-    n += host.SizeOfExcludingThisIfUnshared(mallocSizeOf);
-    n += netInterface.SizeOfExcludingThisIfUnshared(mallocSizeOf);
-    n += originSuffix.SizeOfExcludingThisIfUnshared(mallocSizeOf);
-    return n;
-}
-
-nsHostRecord::nsHostRecord(const nsHostKey& key)
-    : nsHostKey(key)
-    , addr_info_lock("nsHostRecord.addr_info_lock")
+nsHostRecord::nsHostRecord(const nsHostKey *key)
+    : addr_info_lock("nsHostRecord.addr_info_lock")
     , addr_info_gencnt(0)
     , addr_info(nullptr)
     , addr(nullptr)
     , negative(false)
     , resolving(false)
     , onQueue(false)
     , usingAnyThread(false)
     , mDoomed(false)
 #if TTL_AVAILABLE
     , mGetTtl(false)
 #endif
     , mBlacklistedCount(0)
     , mResolveAgain(false)
 {
+    host = ((char *) this) + sizeof(nsHostRecord);
+    memcpy((char *) host, key->host, strlen(key->host) + 1);
+    flags = key->flags;
+    af = key->af;
+    netInterface = host + strlen(key->host) + 1;
+    memcpy((char *) netInterface, key->netInterface,
+           strlen(key->netInterface) + 1);
+    originSuffix = netInterface + strlen(key->netInterface) + 1;
+    memcpy((char *) originSuffix, key->originSuffix,
+           strlen(key->originSuffix) + 1);
     PR_INIT_CLIST(this);
 }
 
 nsresult
 nsHostRecord::Create(const nsHostKey *key, nsHostRecord **result)
 {
-    *result = new nsHostRecord(*key);
+    size_t hostLen = strlen(key->host) + 1;
+    size_t netInterfaceLen = strlen(key->netInterface) + 1;
+    size_t originSuffixLen = strlen(key->originSuffix) + 1;
+    size_t size = hostLen + netInterfaceLen + originSuffixLen + sizeof(nsHostRecord);
+
+    // Use placement new to create the object with room for the hostname,
+    // network interface name and originSuffix allocated after it.
+    void *place = ::operator new(size);
+    *result = new(place) nsHostRecord(key);
     NS_ADDREF(*result);
 
     return NS_OK;
 }
 
 void
 nsHostRecord::SetExpiration(const mozilla::TimeStamp& now, unsigned int valid, unsigned int grace)
 {
@@ -238,66 +235,66 @@ nsHostRecord::~nsHostRecord()
     delete addr_info;
 }
 
 bool
 nsHostRecord::Blacklisted(NetAddr *aQuery)
 {
     // must call locked
     LOG(("Checking blacklist for host [%s%s%s], host record [%p].\n",
-          LOG_HOST(host.get(), netInterface.get()), this));
+          LOG_HOST(host, netInterface), this));
 
     // skip the string conversion for the common case of no blacklist
     if (!mBlacklistedItems.Length()) {
         return false;
     }
 
     char buf[kIPv6CStrBufSize];
     if (!NetAddrToString(aQuery, buf, sizeof(buf))) {
         return false;
     }
     nsDependentCString strQuery(buf);
 
     for (uint32_t i = 0; i < mBlacklistedItems.Length(); i++) {
         if (mBlacklistedItems.ElementAt(i).Equals(strQuery)) {
             LOG(("Address [%s] is blacklisted for host [%s%s%s].\n", buf,
-                 LOG_HOST(host.get(), netInterface.get())));
+                 LOG_HOST(host, netInterface)));
             return true;
         }
     }
 
     return false;
 }
 
 void
 nsHostRecord::ReportUnusable(NetAddr *aAddress)
 {
     // must call locked
     LOG(("Adding address to blacklist for host [%s%s%s], host record [%p].\n",
-         LOG_HOST(host.get(), netInterface.get()), this));
+         LOG_HOST(host, netInterface), this));
 
     ++mBlacklistedCount;
 
     if (negative)
         mDoomed = true;
 
     char buf[kIPv6CStrBufSize];
     if (NetAddrToString(aAddress, buf, sizeof(buf))) {
         LOG(("Successfully adding address [%s] to blacklist for host "
-             "[%s%s%s].\n", buf, LOG_HOST(host.get(), netInterface.get())));
+             "[%s%s%s].\n", buf, LOG_HOST(host, netInterface)));
         mBlacklistedItems.AppendElement(nsCString(buf));
     }
 }
 
 void
 nsHostRecord::ResetBlacklist()
 {
     // must call locked
     LOG(("Resetting blacklist for host [%s%s%s], host record [%p].\n",
-         LOG_HOST(host.get(), netInterface.get()), this));
+         LOG_HOST(host, netInterface), this));
     mBlacklistedItems.Clear();
 }
 
 nsHostRecord::ExpirationStatus
 nsHostRecord::CheckExpiration(const mozilla::TimeStamp& now) const {
     if (!mGraceStart.IsNull() && now >= mGraceStart
             && !mValidEnd.IsNull() && now < mValidEnd) {
         return nsHostRecord::EXP_GRACE;
@@ -342,17 +339,21 @@ SizeOfResolveHostCallbackListExcludingHe
     return n;
 }
 
 size_t
 nsHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
 {
     size_t n = mallocSizeOf(this);
 
-    n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
+    // The |host| field (inherited from nsHostKey) actually points to extra
+    // memory that is allocated beyond the end of the nsHostRecord (see
+    // nsHostRecord::Create()).  So it will be included in the
+    // |mallocSizeOf(this)| call above.
+
     n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
     n += addr_info ? addr_info->SizeOfIncludingThis(mallocSizeOf) : 0;
     n += mallocSizeOf(addr.get());
 
     n += mBlacklistedItems.ShallowSizeOfExcludingThis(mallocSizeOf);
     for (size_t i = 0; i < mBlacklistedItems.Length(); i++) {
         n += mBlacklistedItems[i].SizeOfExcludingThisIfUnshared(mallocSizeOf);
     }
@@ -398,29 +399,33 @@ struct nsHostDBEnt : PLDHashEntryHdr
 {
     nsHostRecord *rec;
 };
 
 static PLDHashNumber
 HostDB_HashKey(const void *key)
 {
     const nsHostKey *hk = static_cast<const nsHostKey *>(key);
-    return AddToHash(HashString(hk->host.get()), RES_KEY_FLAGS(hk->flags),
-                     hk->af, HashString(hk->netInterface.get()),
-                     HashString(hk->originSuffix.get()));
+    return AddToHash(HashString(hk->host), RES_KEY_FLAGS(hk->flags), hk->af,
+                     HashString(hk->netInterface), HashString(hk->originSuffix));
 }
 
 static bool
 HostDB_MatchEntry(const PLDHashEntryHdr *entry,
                   const void *key)
 {
     const nsHostDBEnt *he = static_cast<const nsHostDBEnt *>(entry);
     const nsHostKey *hk = static_cast<const nsHostKey *>(key);
 
-    return *he->rec == *hk;
+    return !strcmp(he->rec->host ? he->rec->host : "",
+                   hk->host ? hk->host : "") &&
+            RES_KEY_FLAGS (he->rec->flags) == RES_KEY_FLAGS(hk->flags) &&
+            he->rec->af == hk->af &&
+            !strcmp(he->rec->netInterface, hk->netInterface) &&
+            !strcmp(he->rec->originSuffix, hk->originSuffix);
 }
 
 static void
 HostDB_MoveEntry(PLDHashTable *table,
                  const PLDHashEntryHdr *from,
                  PLDHashEntryHdr *to)
 {
     static_cast<nsHostDBEnt *>(to)->rec =
@@ -433,32 +438,32 @@ HostDB_ClearEntry(PLDHashTable *table,
 {
     nsHostDBEnt *he = static_cast<nsHostDBEnt*>(entry);
     MOZ_ASSERT(he, "nsHostDBEnt is null!");
 
     nsHostRecord *hr = he->rec;
     MOZ_ASSERT(hr, "nsHostDBEnt has null host record!");
 
     LOG(("Clearing cache db entry for host [%s%s%s].\n",
-         LOG_HOST(hr->host.get(), hr->netInterface.get())));
+         LOG_HOST(hr->host, hr->netInterface)));
 #if defined(DEBUG)
     {
         MutexAutoLock lock(hr->addr_info_lock);
         if (!hr->addr_info) {
             LOG(("No address info for host [%s%s%s].\n",
-                 LOG_HOST(hr->host.get(), hr->netInterface.get())));
+                 LOG_HOST(hr->host, hr->netInterface)));
         } else {
             if (!hr->mValidEnd.IsNull()) {
                 TimeDuration diff = hr->mValidEnd - TimeStamp::NowLoRes();
                 LOG(("Record for host [%s%s%s] expires in %f seconds.\n",
-                     LOG_HOST(hr->host.get(), hr->netInterface.get()),
+                     LOG_HOST(hr->host, hr->netInterface),
                      diff.ToSeconds()));
             } else {
                 LOG(("Record for host [%s%s%s] not yet valid.\n",
-                     LOG_HOST(hr->host.get(), hr->netInterface.get())));
+                     LOG_HOST(hr->host, hr->netInterface)));
             }
 
             NetAddrElement *addrElement = nullptr;
             char buf[kIPv6CStrBufSize];
             do {
                 if (!addrElement) {
                     addrElement = hr->addr_info->mAddresses.getFirst();
                 } else {
@@ -617,17 +622,17 @@ nsHostResolver::FlushCache()
     // Clear the evictionQ and remove all its corresponding entries from
     // the cache first
     if (!PR_CLIST_IS_EMPTY(&mEvictionQ)) {
         PRCList *node = mEvictionQ.next;
         while (node != &mEvictionQ) {
             nsHostRecord *rec = static_cast<nsHostRecord *>(node);
             node = node->next;
             PR_REMOVE_AND_INIT_LINK(rec);
-            mDB.Remove(static_cast<nsHostKey *>(rec));
+            mDB.Remove((nsHostKey *) rec);
             NS_RELEASE(rec);
         }
     }
 
     // Refresh the cache entries that are resolving RIGHT now, remove the rest.
     for (auto iter = mDB.Iter(); !iter.Done(); iter.Next()) {
         auto entry = static_cast<nsHostDBEnt *>(iter.Get());
         // Try to remove the record, or mark it for refresh.
@@ -761,18 +766,17 @@ nsHostResolver::ResolveHost(const char  
             // in the hash table.  if so, then check to see if we can't
             // just reuse the lookup result.  otherwise, if there are
             // any pending callbacks, then add to pending callbacks queue,
             // and return.  otherwise, add ourselves as first pending
             // callback, and proceed to do the lookup.
             nsAutoCString originSuffix;
             aOriginAttributes.CreateSuffix(originSuffix);
 
-            nsHostKey key(nsCString(host), flags, af, nsCString(netInterface),
-                          originSuffix);
+            nsHostKey key = { host, flags, af, netInterface, originSuffix.get() };
             auto he = static_cast<nsHostDBEnt*>(mDB.Add(&key, fallible));
 
             // if the record is null, the hash table OOM'd.
             if (!he) {
                 LOG(("  Out of memory: no cache entry for host [%s%s%s].\n",
                      LOG_HOST(host, netInterface)));
                 rv = NS_ERROR_OUT_OF_MEMORY;
             }
@@ -839,18 +843,18 @@ nsHostResolver::ResolveHost(const char  
             }
 
             // If this is an IPV4 or IPV6 specific request, check if there is
             // an AF_UNSPEC entry we can use. Otherwise, hit the resolver...
             else if (!he->rec->resolving) {
                 if (!(flags & RES_BYPASS_CACHE) &&
                     ((af == PR_AF_INET) || (af == PR_AF_INET6))) {
                     // First, search for an entry with AF_UNSPEC
-                    const nsHostKey unspecKey(nsCString(host), flags, PR_AF_UNSPEC,
-                                              nsCString(netInterface), originSuffix);
+                    const nsHostKey unspecKey = { host, flags, PR_AF_UNSPEC,
+                                                  netInterface, originSuffix.get() };
                     auto unspecHe =
                         static_cast<nsHostDBEnt*>(mDB.Search(&unspecKey));
                     NS_ASSERTION(!unspecHe ||
                                  (unspecHe && unspecHe->rec),
                                 "Valid host entries should contain a record");
                     TimeStamp now = TimeStamp::NowLoRes();
                     if (unspecHe &&
                         unspecHe->rec->HasUsableResult(now, flags)) {
@@ -996,18 +1000,17 @@ nsHostResolver::DetachCallback(const cha
     RefPtr<nsResolveHostCallback> callback(aCallback);
 
     {
         MutexAutoLock lock(mLock);
 
         nsAutoCString originSuffix;
         aOriginAttributes.CreateSuffix(originSuffix);
 
-        nsHostKey key(nsCString(host), flags, af, nsCString(netInterface),
-                      originSuffix);
+        nsHostKey key = { host, flags, af, netInterface, originSuffix.get() };
         auto he = static_cast<nsHostDBEnt*>(mDB.Search(&key));
         if (he) {
             // walk list looking for |callback|... we cannot assume
             // that it will be there!
 
             for (nsResolveHostCallback* c: he->rec->mCallbacks) {
                 if (c == callback) {
                     rec = he->rec;
@@ -1048,17 +1051,17 @@ nsHostResolver::ConditionallyCreateThrea
         if (!thr) {
             mThreadCount--;
             NS_RELEASE_THIS();
             return NS_ERROR_OUT_OF_MEMORY;
         }
     }
     else {
         LOG(("  Unable to find a thread for looking up host [%s%s%s].\n",
-             LOG_HOST(rec->host.get(), rec->netInterface.get())));
+             LOG_HOST(rec->host, rec->netInterface)));
     }
     return NS_OK;
 }
 
 nsresult
 nsHostResolver::IssueLookup(nsHostRecord *rec)
 {
     nsresult rv = NS_OK;
@@ -1210,17 +1213,17 @@ nsHostResolver::GetHostToLookup(nsHostRe
 void
 nsHostResolver::PrepareRecordExpiration(nsHostRecord* rec) const
 {
     MOZ_ASSERT(((bool)rec->addr_info) != rec->negative);
     if (!rec->addr_info) {
         rec->SetExpiration(TimeStamp::NowLoRes(),
                            NEGATIVE_RECORD_LIFETIME, 0);
         LOG(("Caching host [%s%s%s] negative record for %u seconds.\n",
-             LOG_HOST(rec->host.get(), rec->netInterface.get()),
+             LOG_HOST(rec->host, rec->netInterface),
              NEGATIVE_RECORD_LIFETIME));
         return;
     }
 
     unsigned int lifetime = mDefaultCacheLifetime;
     unsigned int grace = mDefaultGracePeriod;
 #if TTL_AVAILABLE
     unsigned int ttl = mDefaultCacheLifetime;
@@ -1231,17 +1234,17 @@ nsHostResolver::PrepareRecordExpiration(
         }
         lifetime = ttl;
         grace = 0;
     }
 #endif
 
     rec->SetExpiration(TimeStamp::NowLoRes(), lifetime, grace);
     LOG(("Caching host [%s%s%s] record for %u seconds (grace %d).",
-         LOG_HOST(rec->host.get(), rec->netInterface.get()), lifetime, grace));
+         LOG_HOST(rec->host, rec->netInterface), lifetime, grace));
 }
 
 static bool
 different_rrset(AddrInfo *rrset1, AddrInfo *rrset2)
 {
     if (!rrset1 || !rrset2) {
         return true;
     }
@@ -1345,32 +1348,32 @@ nsHostResolver::CompleteLookup(nsHostRec
             NS_ADDREF(rec);
             if (mEvictionQSize < mMaxCacheEntries)
                 mEvictionQSize++;
             else {
                 // remove first element on mEvictionQ
                 nsHostRecord *head =
                     static_cast<nsHostRecord *>(PR_LIST_HEAD(&mEvictionQ));
                 PR_REMOVE_AND_INIT_LINK(head);
-                mDB.Remove(static_cast<nsHostKey *>(head));
+                mDB.Remove((nsHostKey *) head);
 
                 if (!head->negative) {
                     // record the age of the entry upon eviction.
                     TimeDuration age = TimeStamp::NowLoRes() - head->mValidStart;
                     Telemetry::Accumulate(Telemetry::DNS_CLEANUP_AGE,
                                           static_cast<uint32_t>(age.ToSeconds() / 60));
                 }
 
                 // release reference to rec owned by mEvictionQ
                 NS_RELEASE(head);
             }
 #if TTL_AVAILABLE
             if (!rec->mGetTtl && !rec->resolving && sGetTtlEnabled) {
                 LOG(("Issuing second async lookup for TTL for host [%s%s%s].",
-                     LOG_HOST(rec->host.get(), rec->netInterface.get())));
+                     LOG_HOST(rec->host, rec->netInterface)));
                 rec->flags =
                   (rec->flags & ~RES_PRIORITY_MEDIUM) | RES_PRIORITY_LOW;
                 DebugOnly<nsresult> rv = IssueLookup(rec);
                 NS_WARNING_ASSERTION(
                     NS_SUCCEEDED(rv),
                     "Could not issue second async lookup for TTL.");
             }
 #endif
@@ -1393,38 +1396,37 @@ nsHostResolver::CancelAsyncRequest(const
                                    uint16_t                af,
                                    const char             *netInterface,
                                    nsIDNSListener         *aListener,
                                    nsresult                status)
 
 {
     MutexAutoLock lock(mLock);
 
-    nsCString originSuffix;
+    nsAutoCString originSuffix;
     aOriginAttributes.CreateSuffix(originSuffix);
 
     // Lookup the host record associated with host, flags & address family
-    nsHostKey key(nsCString(host), flags, af, nsCString(netInterface),
-                  originSuffix);
+    nsHostKey key = { host, flags, af, netInterface, originSuffix.get() };
     auto he = static_cast<nsHostDBEnt*>(mDB.Search(&key));
     if (he) {
         nsHostRecord* recPtr = nullptr;
 
         for (RefPtr<nsResolveHostCallback> c : he->rec->mCallbacks) {
             if (c->EqualsAsyncListener(aListener)) {
                 c->remove();
                 recPtr = he->rec;
                 c->OnResolveHostComplete(this, recPtr, status);
                 break;
             }
         }
 
         // If there are no more callbacks, remove the hash table entry
         if (recPtr && recPtr->mCallbacks.isEmpty()) {
-            mDB.Remove(static_cast<nsHostKey *>(recPtr));
+            mDB.Remove((nsHostKey *)recPtr);
             // If record is on a Queue, remove it and then deref it
             if (recPtr->next != recPtr) {
                 PR_REMOVE_LINK(recPtr);
                 NS_RELEASE(recPtr);
             }
         }
     }
 }
@@ -1465,33 +1467,30 @@ nsHostResolver::ThreadFunc(void *arg)
     nsResState rs;
 #endif
     RefPtr<nsHostResolver> resolver = dont_AddRef((nsHostResolver *)arg);
     nsHostRecord *rec  = nullptr;
     AddrInfo *ai = nullptr;
 
     while (rec || resolver->GetHostToLookup(&rec)) {
         LOG(("DNS lookup thread - Calling getaddrinfo for host [%s%s%s].\n",
-             LOG_HOST(rec->host.get(), rec->netInterface.get())));
+             LOG_HOST(rec->host, rec->netInterface)));
 
         TimeStamp startTime = TimeStamp::Now();
 #if TTL_AVAILABLE
         bool getTtl = rec->mGetTtl;
 #else
         bool getTtl = false;
 #endif
 
-        nsresult status = GetAddrInfo(rec->host.get(), rec->af,
-                                      rec->flags,
-                                      rec->netInterface.get(), &ai,
-                                      getTtl);
+        nsresult status = GetAddrInfo(rec->host, rec->af, rec->flags, rec->netInterface,
+                                      &ai, getTtl);
 #if defined(RES_RETRY_ON_FAILURE)
         if (NS_FAILED(status) && rs.Reset()) {
-            status = GetAddrInfo(rec->host.get(), rec->af,
-                                 rec->flags, rec->netInterface, &ai,
+            status = GetAddrInfo(rec->host, rec->af, rec->flags, rec->netInterface, &ai,
                                  getTtl);
         }
 #endif
 
         {   // obtain lock to check shutdown and manage inter-module telemetry
             MutexAutoLock lock(resolver->mLock);
 
             if (!resolver->mShutdown) {
@@ -1514,23 +1513,23 @@ nsHostResolver::ThreadFunc(void *arg)
                 } else {
                     Telemetry::Accumulate(Telemetry::DNS_FAILED_LOOKUP_TIME, millis);
                 }
             }
         }
 
         // CompleteLookup may release "rec", long before we lose it.
         LOG(("DNS lookup thread - lookup completed for host [%s%s%s]: %s.\n",
-             LOG_HOST(rec->host.get(), rec->netInterface.get()),
+             LOG_HOST(rec->host, rec->netInterface),
              ai ? "success" : "failure: unknown host"));
 
         if (LOOKUP_RESOLVEAGAIN == resolver->CompleteLookup(rec, status, ai)) {
             // leave 'rec' assigned and loop to make a renewed host resolve
             LOG(("DNS lookup thread - Re-resolving host [%s%s%s].\n",
-                 LOG_HOST(rec->host.get(), rec->netInterface.get())));
+                 LOG_HOST(rec->host, rec->netInterface)));
         } else {
             rec = nullptr;
         }
     }
     resolver->mThreadCount--;
     resolver = nullptr;
     LOG(("DNS lookup thread - queue empty, thread finished.\n"));
 }
@@ -1557,17 +1556,17 @@ void
 nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries> *args)
 {
     for (auto iter = mDB.Iter(); !iter.Done(); iter.Next()) {
         // We don't pay attention to address literals, only resolved domains.
         // Also require a host.
         auto entry = static_cast<nsHostDBEnt*>(iter.Get());
         nsHostRecord* rec = entry->rec;
         MOZ_ASSERT(rec, "rec should never be null here!");
-        if (!rec || !rec->addr_info) {
+        if (!rec || !rec->addr_info || !rec->host) {
             continue;
         }
 
         DNSCacheEntries info;
         info.hostname = rec->host;
         info.family = rec->af;
         info.netInterface = rec->netInterface;
         info.expiration =
--- a/netwerk/dns/nsHostResolver.h
+++ b/netwerk/dns/nsHostResolver.h
@@ -32,49 +32,35 @@ class nsResolveHostCallback;
 #define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 5
 #define MAX_NON_PRIORITY_REQUESTS 150
 
 #define MAX_RESOLVER_THREADS (MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \
                               MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY)
 
 struct nsHostKey
 {
-    const nsCString host;
-    uint16_t flags;
-    uint16_t af;
-    const nsCString netInterface;
-    const nsCString originSuffix;
-
-    nsHostKey(const nsACString& host, uint16_t flags,
-              uint16_t af, const nsACString& netInterface,
-              const nsACString& originSuffix)
-        : host(host)
-        , flags(flags)
-        , af(af)
-        , netInterface(netInterface)
-        , originSuffix(originSuffix) {
-    }
-
-    bool operator==(const nsHostKey& other) const;
-    size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+    const char *host;
+    uint16_t    flags;
+    uint16_t    af;
+    const char *netInterface;
+    const char *originSuffix;
 };
 
 /**
  * nsHostRecord - ref counted object type stored in host resolver cache.
  */
 class nsHostRecord : public PRCList, public nsHostKey
 {
     typedef mozilla::Mutex Mutex;
 
 public:
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHostRecord)
 
     /* instantiates a new host record */
     static nsresult Create(const nsHostKey *key, nsHostRecord **record);
-    nsHostRecord(const nsHostKey& key);
 
     /* a fully resolved host record has either a non-null |addr_info| or |addr|
      * field.  if |addr_info| is null, it implies that the |host| is an IP
      * address literal.  in which case, |addr| contains the parsed address.
      * otherwise, if |addr_info| is non-null, then it contains one or many
      * IP addresses corresponding to the given host name.  if both |addr_info|
      * and |addr| are null, then the given host has not yet been fully resolved.
      * |af| is the address family of the record we are querying for.