Bug 592308. IsLowMemory() is terribly slow and there is nothing to do about it. r=bsmedberg a=blocking-fennec2.0
authorDoug Turner <dougt@dougt.org>
Thu, 02 Sep 2010 19:02:06 -0300
changeset 51934 a5d1b45234b8f9681a6418e41a154dc78b962fab
parent 51933 26cb1dc486377973880d5db9f5db705b04ab4b9a
child 51935 983c38bb0f03d49d17989c0dc081ebcd8603905f
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg, blocking-fennec2.0
bugs592308
milestone2.0b6pre
Bug 592308. IsLowMemory() is terribly slow and there is nothing to do about it. r=bsmedberg a=blocking-fennec2.0
dom/base/nsJSEnvironment.cpp
modules/libpr0n/src/imgFrame.cpp
xpcom/base/nsIMemory.idl
xpcom/base/nsMemoryImpl.cpp
xpcom/tests/Makefile.in
xpcom/tests/TestOOM.cpp
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -956,101 +956,27 @@ nsJSContext::DOMOperationCallback(JSCont
   PRTime modalStateTime = ctx->mModalStateTime;
 
   MaybeGC(cx);
 
   // Now restore the callback time and count, in case they got reset.
   ctx->mOperationCallbackTime = callbackTime;
   ctx->mModalStateTime = modalStateTime;
 
-  // Check to see if we are running OOM
-  nsCOMPtr<nsIMemory> mem;
-  NS_GetMemoryManager(getter_AddRefs(mem));
-  if (!mem) {
-    JS_ClearPendingException(cx);
-    return JS_FALSE;
-  }
-
-  PRBool lowMemory;
-  mem->IsLowMemory(&lowMemory);
-  if (lowMemory) {
-    // try to clean up:
-    nsJSContext::CC();
-
-    // never prevent system scripts from running
-    if (!::JS_IsSystemObject(cx, ::JS_GetGlobalObject(cx))) {
-
-      // lets see if CC() did anything, if not, cancel the script.
-      mem->IsLowMemory(&lowMemory);
-      if (lowMemory) {
-
-        if (nsContentUtils::GetBoolPref("dom.prevent_oom_dialog", PR_FALSE)) {
-          JS_ClearPendingException(cx);
-          return JS_FALSE;
-        }
-
-        nsCOMPtr<nsIScriptError> errorObject =
-          do_CreateInstance("@mozilla.org/scripterror;1");
-
-        if (errorObject) {
-          nsXPIDLString msg;
-          nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
-                                             "LowMemoryMessage",
-                                             msg);
-
-          JSStackFrame *fp, *iterator = nsnull;
-          fp = ::JS_FrameIterator(cx, &iterator);
-          PRUint32 lineno = 0;
-          nsAutoString sourcefile;
-          if (fp) {
-            JSScript* script = ::JS_GetFrameScript(cx, fp);
-            if (script) {
-              const char* filename = ::JS_GetScriptFilename(cx, script);
-              if (filename) {
-                CopyUTF8toUTF16(nsDependentCString(filename), sourcefile);
-              }
-              jsbytecode* pc = ::JS_GetFramePC(cx, fp);
-              if (pc) {
-                lineno = ::JS_PCToLineNumber(cx, script, pc);
-              }
-            }
-          }
-
-          rv = errorObject->Init(msg.get(),
-                                 sourcefile.get(),
-                                 EmptyString().get(),
-                                 lineno, 0, nsIScriptError::errorFlag,
-                                 "content javascript");
-          if (NS_SUCCEEDED(rv)) {
-            nsCOMPtr<nsIConsoleService> consoleService =
-              do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv);
-            if (NS_SUCCEEDED(rv)) {
-              consoleService->LogMessage(errorObject);
-            }
-          }
-        }
-
-        JS_ClearPendingException(cx);
-        return JS_FALSE;
-      }
-    }
-  }
-
   PRTime now = PR_Now();
 
   if (callbackTime == 0) {
     // Initialize mOperationCallbackTime to start timing how long the
     // script has run
     ctx->mOperationCallbackTime = now;
     return JS_TRUE;
   }
 
   if (ctx->mModalStateDepth) {
     // We're waiting on a modal dialog, nothing more to do here.
-
     return JS_TRUE;
   }
 
   PRTime duration = now - callbackTime;
 
   // Check the amount of time this script has been running, or if the
   // dialog is disabled.
   PRBool isTrackingChromeCodeTime =
--- a/modules/libpr0n/src/imgFrame.cpp
+++ b/modules/libpr0n/src/imgFrame.cpp
@@ -187,27 +187,16 @@ imgFrame::~imgFrame()
 
 nsresult imgFrame::Init(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, 
                         gfxASurface::gfxImageFormat aFormat, PRInt8 aPaletteDepth /* = 0 */)
 {
   // assert for properties that should be verified by decoders, warn for properties related to bad content
   if (!AllowedImageSize(aWidth, aHeight))
     return NS_ERROR_FAILURE;
 
-  // Check to see if we are running OOM
-  nsCOMPtr<nsIMemory> mem;
-  NS_GetMemoryManager(getter_AddRefs(mem));
-  if (!mem)
-    return NS_ERROR_UNEXPECTED;
-
-  PRBool lowMemory;
-  mem->IsLowMemory(&lowMemory);
-  if (lowMemory)
-    return NS_ERROR_OUT_OF_MEMORY;
-
   mOffset.MoveTo(aX, aY);
   mSize.SizeTo(aWidth, aHeight);
 
   mFormat = aFormat;
   mPaletteDepth = aPaletteDepth;
 
   if (aPaletteDepth != 0) {
     // We're creating for a paletted image.
@@ -548,27 +537,16 @@ nsresult imgFrame::Extract(const nsIntRe
 
   *aResult = subImage.forget();
 
   return NS_OK;
 }
 
 nsresult imgFrame::ImageUpdated(const nsIntRect &aUpdateRect)
 {
-  // Check to see if we are running OOM
-  nsCOMPtr<nsIMemory> mem;
-  NS_GetMemoryManager(getter_AddRefs(mem));
-  if (!mem)
-    return NS_ERROR_UNEXPECTED;
-
-  PRBool lowMemory;
-  mem->IsLowMemory(&lowMemory);
-  if (lowMemory)
-    return NS_ERROR_OUT_OF_MEMORY;
-
   mDecoded.UnionRect(mDecoded, aUpdateRect);
 
   // clamp to bounds, in case someone sends a bogus updateRect (I'm looking at
   // you, gif decoder)
   nsIntRect boundsRect(mOffset, mSize);
   mDecoded.IntersectRect(mDecoded, boundsRect);
 
 #ifdef XP_MACOSX
--- a/xpcom/base/nsIMemory.idl
+++ b/xpcom/base/nsIMemory.idl
@@ -117,12 +117,14 @@ interface nsIMemory : nsISupports
      *   was not on the application's main thread.
      */
     void heapMinimize(in boolean immediate);
 
     /**
      * This predicate can be used to determine if we're in a low-memory
      * situation (what constitutes low-memory is platform dependent). This
      * can be used to trigger the memory pressure observers.
+     *
+     * DEPRECATED - Always returns false.  See bug 592308.
      */
     boolean isLowMemory();
 };
 
--- a/xpcom/base/nsMemoryImpl.cpp
+++ b/xpcom/base/nsMemoryImpl.cpp
@@ -49,40 +49,16 @@
 #include "pratom.h"
 
 #include "nsAlgorithm.h"
 #include "nsAutoLock.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "mozilla/Services.h"
 
-#if defined(XP_WIN)
-#include <windows.h>
-#endif
-
-#if (MOZ_PLATFORM_MAEMO == 5 || MOZ_PLATFORM_MAEMO == 4) && defined(__arm__)
-#include <fcntl.h>
-#include <unistd.h>
-static const char kHighMark[] = "/sys/kernel/high_watermark";
-#endif
-
-// Some platforms notify you when system memory is low, others do not.
-// In the case of those that do not, we want to post low memory
-// notifications from IsLowMemory().  For those that can notify us, that
-// code usually lives in toolkit.
-#ifdef WINCE
-#define NOTIFY_LOW_MEMORY
-#endif
-
-#ifdef WINCE_WINDOWS_MOBILE
-#include "aygshell.h"
-#endif
-
-#include "nsITimer.h"
-
 static nsMemoryImpl sGlobalMemory;
 
 NS_IMPL_QUERY_INTERFACE1(nsMemoryImpl, nsIMemory)
 
 NS_IMETHODIMP_(void*)
 nsMemoryImpl::Alloc(PRSize size)
 {
     return NS_Alloc(size);
@@ -101,66 +77,21 @@ nsMemoryImpl::Free(void* ptr)
 }
 
 NS_IMETHODIMP
 nsMemoryImpl::HeapMinimize(PRBool aImmediate)
 {
     return FlushMemory(NS_LITERAL_STRING("heap-minimize").get(), aImmediate);
 }
 
-/* this magic number is something greater than 40mb
- * and after all, 40mb should be good enough for any web app
- * unless it's part of an office suite.
- */
-static const int kRequiredMemory = 0x3000000;
-
 NS_IMETHODIMP
 nsMemoryImpl::IsLowMemory(PRBool *result)
 {
-#if defined(WINCE_WINDOWS_MOBILE)
-    MEMORYSTATUS stat;
-    GlobalMemoryStatus(&stat);
-    *result = (stat.dwMemoryLoad >= 98);
-#elif defined(WINCE)
-    // Bug 525323 - GlobalMemoryStatus kills perf on WinCE.
+    NS_ERROR("IsLowMemory is deprecated.  See bug 592308.");
     *result = PR_FALSE;
-#elif defined(XP_WIN)
-    MEMORYSTATUSEX stat;
-    stat.dwLength = sizeof stat;
-    GlobalMemoryStatusEx(&stat);
-    *result = (stat.ullAvailPageFile < kRequiredMemory) &&
-        ((float)stat.ullAvailPageFile / stat.ullTotalPageFile) < 0.1;
-#elif (MOZ_PLATFORM_MAEMO == 5 || MOZ_PLATFORM_MAEMO == 4) && defined(__arm__)
-    static int osso_highmark_fd = -1;
-    if (osso_highmark_fd == -1) {
-        osso_highmark_fd = open (kHighMark, O_RDONLY);
-
-        if (osso_highmark_fd == -1) {
-            NS_ERROR("can't find the osso highmark file");    
-            *result = PR_FALSE;
-            return NS_OK;
-        }
-    }
-
-    // be kind, rewind.
-    lseek(osso_highmark_fd, 0L, SEEK_SET);
-
-    int c = 0;
-    read (osso_highmark_fd, &c, 1);
-
-    *result = (c == '1');
-#else
-    *result = PR_FALSE;
-#endif
-
-#ifdef NOTIFY_LOW_MEMORY
-    if (*result) {
-        sGlobalMemory.FlushMemory(NS_LITERAL_STRING("low-memory").get(), PR_FALSE);
-    }
-#endif
     return NS_OK;
 }
 
 /*static*/ nsresult
 nsMemoryImpl::Create(nsISupports* outer, const nsIID& aIID, void **aResult)
 {
     NS_ENSURE_NO_AGGREGATION(outer);
     return sGlobalMemory.QueryInterface(aIID, aResult);
--- a/xpcom/tests/Makefile.in
+++ b/xpcom/tests/Makefile.in
@@ -68,17 +68,16 @@ endif
 CPPSRCS		= \
 		nsIFileEnumerator.cpp \
 		TestCallTemplates.cpp \
 		TestINIParser.cpp \
 		TestRacingServiceManager.cpp \
 		TestRegistrationOrder.cpp \
 		TestThreadPoolListener.cpp \
 		TestTimers.cpp \
-		TestOOM.cpp \
 		TestBlockingProcess.cpp \
 		TestQuickReturn.cpp \
 		TestArguments.cpp \
 		TestUnicodeArguments.cpp \
 		$(NULL)
 
 ifdef WRAP_STL_INCLUDES
 CPPSRCS += TestSTLWrappers.cpp
deleted file mode 100644
--- a/xpcom/tests/TestOOM.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/* ***** 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 a simple OOM Test.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Doug Turner <dougt@meer.net>
- *
- * 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>
-#include <stdlib.h>
-#include <math.h>
-
-#include "nsXPCOM.h"
-#include "nsISupportsUtils.h"
-#include "nsCOMPtr.h"
-#include "nsIMemory.h"
-
-int main(int argc, char **argv)
-{
-  nsCOMPtr<nsIMemory> mem;
-  nsresult rv = NS_GetMemoryManager(getter_AddRefs(mem));
-
-  if (!mem || NS_FAILED(rv))
-  {
-    printf("Could not get the memory manager\n");
-    return -1;
-  }
-
-  // allocation note.  don't use nsIMemory to allocate,
-  // because we want to test the isLowMemory predicate
-  // without regard for the nsIMemory impelmentation (the
-  // implementation might count bytes handed out.  however,
-  // the predicate should work with out having to rely on
-  // that.
-  void *big_alloc = malloc(1024 * 1024 * 16);
-  (void)big_alloc; // Tell compiler we're not using big_alloc, to fix warning
-
-  const int highpower = 500000;
-  
-  char* buffers[highpower];
-  for (int i=0; i<highpower; i++)
-    buffers[i] = nsnull;
-  
-  for (int i=0; i<highpower; i++)
-  {
-    PRBool lowMem = PR_FALSE;
-    size_t s = 4096; //pow(2,i);
-    buffers[i] = (char*) malloc(s);
-    
-    // You have to touch the buffer
-    if (!buffers[i])
-      printf("Could not allocate a buffer of size %lu\n", (unsigned long)s);
-    else
-    {
-      for (size_t j=0; j<s; j++)
-        buffers[i][j] = 'a';
-    }
-   
-    PRIntervalTime start = PR_IntervalNow();
-    mem->IsLowMemory(&lowMem);
-    PRIntervalTime cost = PR_IntervalNow() - start;
-    
-    
-    printf("Total Allocated: %lu. \tLow Memory now?  %s\t Took (%d)\n",
-           (unsigned long)s*i,
-           lowMem ? "Yes" : "No",
-           PR_IntervalToMilliseconds(cost));
-  
-    if (lowMem)
-      break;
-  }
-
-  for(int i=0; i<highpower; i++)
-  {
-    if (buffers[i])
-      free(buffers[i]);
-  }
-  return 0;
-}