Merge last green changeset of mozilla-inbound to mozilla-central
authorEd Morley <bmo@edmorley.co.uk>
Thu, 06 Oct 2011 11:14:24 +0100
changeset 78824 f107192c7d5936c81814f00967f580aaca99ed32
parent 78804 8c82de08425d6fc7a9b235311d07ed4f6af0717e (current diff)
parent 78823 7e1f77774d9eee2b3d1b6b6baaa0c4656bfa5b0d (diff)
child 78829 62ea504b378d32e3b10cb6358a5ae869285eb7e5
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone10.0a1
Merge last green changeset of mozilla-inbound to mozilla-central
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -47,38 +47,40 @@
 
 #include "ContentChild.h"
 #include "CrashReporterChild.h"
 #include "TabChild.h"
 #if defined(MOZ_SYDNEYAUDIO)
 #include "AudioChild.h"
 #endif
 
+#include "mozilla/dom/ExternalHelperAppChild.h"
+#include "mozilla/dom/PCrashReporterChild.h"
+#include "mozilla/dom/StorageChild.h"
+#include "mozilla/hal_sandbox/PHalChild.h"
 #include "mozilla/ipc/TestShellChild.h"
-#include "mozilla/net/NeckoChild.h"
 #include "mozilla/ipc/XPCShellEnvironment.h"
 #include "mozilla/jsipc/PContextWrapperChild.h"
-#include "mozilla/dom/ExternalHelperAppChild.h"
-#include "mozilla/dom/StorageChild.h"
-#include "mozilla/dom/PCrashReporterChild.h"
+#include "mozilla/net/NeckoChild.h"
 
 #if defined(MOZ_SYDNEYAUDIO)
 #include "nsAudioStream.h"
 #endif
 #include "nsIMemoryReporter.h"
 #include "nsIObserverService.h"
 #include "nsTObserverArray.h"
 #include "nsIObserver.h"
 #include "nsIPrefService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsXULAppAPI.h"
 #include "nsWeakReference.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsJSEnvironment.h"
+#include "SandboxHal.h"
 
 #include "History.h"
 #include "nsDocShellCID.h"
 #include "nsNetUtil.h"
 
 #include "base/message_loop.h"
 #include "base/task.h"
 
@@ -104,16 +106,17 @@
 #include <process.h>
 #define getpid _getpid
 #endif
 
 #ifdef ACCESSIBILITY
 #include "nsIAccessibilityService.h"
 #endif
 
+using namespace mozilla::hal_sandbox;
 using namespace mozilla::ipc;
 using namespace mozilla::net;
 using namespace mozilla::places;
 using namespace mozilla::docshell;
 
 namespace mozilla {
 namespace dom {
 
@@ -435,16 +438,29 @@ ContentChild::AllocPCrashReporter(const 
 
 bool
 ContentChild::DeallocPCrashReporter(PCrashReporterChild* crashreporter)
 {
     delete crashreporter;
     return true;
 }
 
+PHalChild*
+ContentChild::AllocPHal()
+{
+    return CreateHalChild();
+}
+
+bool
+ContentChild::DeallocPHal(PHalChild* aHal)
+{
+    delete aHal;
+    return true;
+}
+
 PTestShellChild*
 ContentChild::AllocPTestShell()
 {
     return new TestShellChild();
 }
 
 bool
 ContentChild::DeallocPTestShell(PTestShellChild* shell)
@@ -784,10 +800,18 @@ ContentChild::RecvGarbageCollect()
 bool
 ContentChild::RecvCycleCollect()
 {
     nsJSContext::GarbageCollectNow();
     nsJSContext::CycleCollectNow();
     return true;
 }
 
+bool
+ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID)
+{
+    mAppInfo.version.Assign(version);
+    mAppInfo.buildID.Assign(buildID);
+    return true;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -59,38 +59,51 @@ class ConsoleListener;
 class PStorageChild;
 
 class ContentChild : public PContentChild
 {
 public:
     ContentChild();
     virtual ~ContentChild();
 
+    struct AppInfo
+    {
+        nsCString version;
+        nsCString buildID;
+    };
+
     bool Init(MessageLoop* aIOLoop,
               base::ProcessHandle aParentHandle,
               IPC::Channel* aChannel);
     void InitXPCOM();
 
     static ContentChild* GetSingleton() {
         NS_ASSERTION(sSingleton, "not initialized");
         return sSingleton;
     }
 
+    const AppInfo& GetAppInfo() {
+        return mAppInfo;
+    }
+
     /* if you remove this, please talk to cjones or dougt */
     virtual bool RecvDummy(Shmem& foo) { return true; }
 
     virtual PBrowserChild* AllocPBrowser(const PRUint32& aChromeFlags);
     virtual bool DeallocPBrowser(PBrowserChild*);
 
     virtual PCrashReporterChild*
     AllocPCrashReporter(const mozilla::dom::NativeThreadId& id,
                         const PRUint32& processType);
     virtual bool
     DeallocPCrashReporter(PCrashReporterChild*);
 
+    NS_OVERRIDE virtual PHalChild* AllocPHal();
+    NS_OVERRIDE virtual bool DeallocPHal(PHalChild*);
+
     virtual PMemoryReportRequestChild*
     AllocPMemoryReportRequest();
 
     virtual bool
     DeallocPMemoryReportRequest(PMemoryReportRequestChild* actor);
 
     virtual bool
     RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child);
@@ -149,16 +162,18 @@ public:
 
     virtual bool RecvFlushMemory(const nsString& reason);
 
     virtual bool RecvActivateA11y();
 
     virtual bool RecvGarbageCollect();
     virtual bool RecvCycleCollect();
 
+    virtual bool RecvAppInfo(const nsCString& version, const nsCString& buildID);
+
 #ifdef ANDROID
     gfxIntSize GetScreenSize() { return mScreenSize; }
 #endif
 
     // Get the directory for IndexedDB files. We query the parent for this and
     // cache the value
     nsString &GetIndexedDBPath();
 
@@ -176,16 +191,18 @@ private:
     NS_NORETURN void QuickExit();
 
     InfallibleTArray<nsAutoPtr<AlertObserver> > mAlertObservers;
     nsRefPtr<ConsoleListener> mConsoleListener;
 #ifdef ANDROID
     gfxIntSize mScreenSize;
 #endif
 
+    AppInfo mAppInfo;
+
     static ContentChild* sSingleton;
 
     DISALLOW_EVIL_CONSTRUCTORS(ContentChild);
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -66,20 +66,22 @@
 #include "nsIPresShell.h"
 #include "nsIAlertsService.h"
 #include "nsToolkitCompsCID.h"
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsConsoleMessage.h"
 #include "nsAppDirectoryServiceDefs.h"
+#include "nsAppRunner.h"
 #include "IDBFactory.h"
 #if defined(MOZ_SYDNEYAUDIO)
 #include "AudioParent.h"
 #endif
+#include "SandboxHal.h"
 
 #if defined(ANDROID) || defined(LINUX)
 #include <sys/time.h>
 #include <sys/resource.h>
 #include "nsSystemInfo.h"
 #endif
 
 #ifdef MOZ_PERMISSIONS
@@ -88,16 +90,17 @@
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsICrashReporter.h"
 #include "nsExceptionHandler.h"
 #endif
 
 #include "mozilla/dom/ExternalHelperAppParent.h"
 #include "mozilla/dom/StorageParent.h"
+#include "mozilla/hal_sandbox/PHalParent.h"
 #include "mozilla/Services.h"
 #include "mozilla/unused.h"
 #include "nsDeviceMotion.h"
 #include "mozilla/Util.h"
 
 #include "nsIMemoryReporter.h"
 #include "nsMemoryReporterManager.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
@@ -110,16 +113,17 @@
 #include "nsIClipboard.h"
 #include "nsWidgetsCID.h"
 #include "nsISupportsPrimitives.h"
 static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
 static const char* sClipboardTextFlavors[] = { kUnicodeMime };
 
 using mozilla::Preferences;
 using namespace mozilla::ipc;
+using namespace mozilla::hal_sandbox;
 using namespace mozilla::net;
 using namespace mozilla::places;
 using mozilla::unused; // heh
 using base::KillProcess;
 
 namespace mozilla {
 namespace dom {
 
@@ -422,16 +426,24 @@ ContentParent::ContentParent()
     mSubprocess->AsyncLaunch();
     Open(mSubprocess->GetChannel(), mSubprocess->GetChildProcessHandle());
 
     nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
     nsChromeRegistryChrome* chromeRegistry =
         static_cast<nsChromeRegistryChrome*>(registrySvc.get());
     chromeRegistry->SendRegisteredChrome(this);
     mMessageManager = nsFrameMessageManager::NewProcessMessageManager(this);
+
+    if (gAppData) {
+        nsCString version(gAppData->version);
+        nsCString buildID(gAppData->buildID);
+
+        //Sending all information to content process
+        SendAppInfo(version, buildID);
+    }
 }
 
 ContentParent::~ContentParent()
 {
     if (OtherProcess())
         base::CloseProcessHandle(OtherProcess());
 
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@@ -806,16 +818,29 @@ ContentParent::RecvPCrashReporterConstru
 
 bool
 ContentParent::DeallocPCrashReporter(PCrashReporterParent* crashreporter)
 {
   delete crashreporter;
   return true;
 }
 
+PHalParent*
+ContentParent::AllocPHal()
+{
+    return CreateHalParent();
+}
+
+bool
+ContentParent::DeallocPHal(PHalParent* aHal)
+{
+    delete aHal;
+    return true;
+}
+
 PMemoryReportRequestParent*
 ContentParent::AllocPMemoryReportRequest()
 {
   MemoryReportRequestParent* parent = new MemoryReportRequestParent();
   return parent;
 }
 
 bool
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -130,16 +130,19 @@ private:
 
     virtual PCrashReporterParent* AllocPCrashReporter(const NativeThreadId& tid,
                                                       const PRUint32& processType);
     virtual bool DeallocPCrashReporter(PCrashReporterParent* crashreporter);
     virtual bool RecvPCrashReporterConstructor(PCrashReporterParent* actor,
                                                const NativeThreadId& tid,
                                                const PRUint32& processType);
 
+    NS_OVERRIDE virtual PHalParent* AllocPHal();
+    NS_OVERRIDE virtual bool DeallocPHal(PHalParent*);
+
     virtual PMemoryReportRequestParent* AllocPMemoryReportRequest();
     virtual bool DeallocPMemoryReportRequest(PMemoryReportRequestParent* actor);
 
     virtual PTestShellParent* AllocPTestShell();
     virtual bool DeallocPTestShell(PTestShellParent* shell);
 
     virtual PAudioParent* AllocPAudio(const PRInt32&,
                                      const PRInt32&,
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -102,16 +102,18 @@ LOCAL_INCLUDES += \
 	-I$(topsrcdir)/uriloader/exthandler \
 	-I$(srcdir)/../../netwerk/base/src \
 	-I$(srcdir)/../src/base \
 	-I$(srcdir)/../src/storage \
 	-I$(srcdir)/../../xpcom/base \
 	-I$(srcdir)/../indexedDB \
 	-I$(topsrcdir)/extensions/cookie \
 	-I$(topsrcdir)/dom/base \
+	-I$(topsrcdir)/toolkit/xre \
+	-I$(topsrcdir)/hal/sandbox \
 	$(NULL)
 
 DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'
 
 ifdef MOZ_PERMISSIONS
 DEFINES += -DMOZ_PERMISSIONS
 endif
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -34,21 +34,22 @@
  * 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 protocol PAudio;
 include protocol PBrowser;
 include protocol PCrashReporter;
-include protocol PTestShell;
+include protocol PExternalHelperApp;
+include protocol PHal;
+include protocol PMemoryReportRequest;
 include protocol PNecko;
-include protocol PExternalHelperApp;
 include protocol PStorage;
-include protocol PMemoryReportRequest;
+include protocol PTestShell;
 
 include "mozilla/chrome/RegistryMessageUtils.h";
 include "mozilla/net/NeckoMessageUtils.h";
 include "mozilla/dom/TabMessageUtils.h";
 
 include "nsGeoPositionIPCSerialiser.h";
 include "PPrefTuple.h";
 
@@ -94,21 +95,22 @@ struct FontListEntry {
     PRUint8   index;
 };
 
 rpc protocol PContent
 {
     manages PAudio;
     manages PBrowser;
     manages PCrashReporter;
-    manages PTestShell;
+    manages PExternalHelperApp;
+    manages PHal;
+    manages PMemoryReportRequest;
     manages PNecko;
-    manages PExternalHelperApp;
     manages PStorage;
-    manages PMemoryReportRequest;
+    manages PTestShell;
 
 child:
     PBrowser(PRUint32 chromeFlags);
 
     PMemoryReportRequest();
 
     PTestShell();
 
@@ -138,25 +140,29 @@ child:
     GarbageCollect();
     CycleCollect();
     
     /**
      * Start accessibility engine in content process.
      */
     ActivateA11y();
 
+    AppInfo(nsCString version, nsCString buildID);
+
 parent:
+    PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
+
+    sync PCrashReporter(NativeThreadId tid, PRUint32 processType);
+
+    PHal();
+
     PNecko();
     
     PStorage(StorageConstructData data);
 
-    PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
-
-    sync PCrashReporter(NativeThreadId tid, PRUint32 processType);
-
     // Services remoting
 
     async StartVisitedQuery(URI uri);
     async VisitURI(URI uri, URI referrer, PRUint32 flags);
     async SetURITitle(URI uri, nsString title);
     
     // filepicker remoting
     sync ShowFilePicker(PRInt16 mode, PRInt16 selectedType, bool addToRecentDocs,
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -637,16 +637,18 @@ DrawTargetD2D::DrawSurfaceWithShadow(Sou
   mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), NULL, 0xffffffff);
 
   mDevice->Draw(4, 0);
 }
 
 void
 DrawTargetD2D::ClearRect(const Rect &aRect)
 {
+  MarkChanged();
+
   mRT->SetTransform(D2DMatrix(mTransform));
   PopAllClips();
 
   AutoSaveRestoreClippedOut restoreClippedOut(this);
 
   restoreClippedOut.Save();
 
   bool needsClip = false;
@@ -665,16 +667,18 @@ DrawTargetD2D::ClearRect(const Rect &aRe
   return;
 }
 
 void
 DrawTargetD2D::CopySurface(SourceSurface *aSurface,
                            const IntRect &aSourceRect,
                            const IntPoint &aDestination)
 {
+  MarkChanged();
+
   Rect srcRect(Float(aSourceRect.x), Float(aSourceRect.y),
                Float(aSourceRect.width), Float(aSourceRect.height));
   Rect dstRect(Float(aDestination.x), Float(aDestination.y),
                Float(aSourceRect.width), Float(aSourceRect.height));
 
   mRT->SetTransform(D2D1::IdentityMatrix());
   mRT->PushAxisAlignedClip(D2DRect(dstRect), D2D1_ANTIALIAS_MODE_ALIASED);
   mRT->Clear(D2D1::ColorF(0, 0.0f));
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -256,17 +256,17 @@ CanvasLayerOGL::RenderLayer(int aPreviou
   }
 
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
   if (mPixmap && !mDelayedUpdates) {
     sGLXLibrary.BindTexImage(mPixmap);
   }
 #endif
 
-  ApplyFilter(mFilter);
+  gl()->ApplyFilterToBoundTexture(mFilter);
 
   program->Activate();
   program->SetLayerQuadRect(drawRect);
   program->SetLayerTransform(GetEffectiveTransform());
   program->SetLayerOpacity(GetEffectiveOpacity());
   program->SetRenderOffset(aOffset);
   program->SetTextureUnit(0);
 
@@ -361,23 +361,23 @@ void
 ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer,
                                   const nsIntPoint& aOffset)
 {
   mOGLManager->MakeCurrent();
 
   ColorTextureLayerProgram *program =
     mOGLManager->GetColorTextureLayerProgram(mTexImage->GetShaderProgramType());
 
-  ApplyFilter(mFilter);
+  mTexImage->SetFilter(mFilter);
 
   program->Activate();
   program->SetLayerTransform(GetEffectiveTransform());
   program->SetLayerOpacity(GetEffectiveOpacity());
   program->SetRenderOffset(aOffset);
   program->SetTextureUnit(0);
 
   mTexImage->BeginTileIteration();
   do {
-    TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
+    TextureImage::ScopedBindTextureAndApplyFilter texBind(mTexImage, LOCAL_GL_TEXTURE0);
     program->SetLayerQuadRect(mTexImage->GetTileRect());
     mOGLManager->BindAndDrawQuad(program, mNeedsYFlip); // FIXME flip order of tiles?
   } while (mTexImage->NextTile());
 }
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -423,23 +423,23 @@ ImageLayerOGL::RenderLayer(int,
     if (!yuvImage->HasTextures()) {
       yuvImage->AllocateTextures(gl());
     }
 
     yuvImage->UpdateTextures(gl());
 
     gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[0].GetTextureID());
-    ApplyFilter(mFilter);
+    gl()->ApplyFilterToBoundTexture(mFilter);
     gl()->fActiveTexture(LOCAL_GL_TEXTURE1);
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[1].GetTextureID());
-    ApplyFilter(mFilter);
+    gl()->ApplyFilterToBoundTexture(mFilter);
     gl()->fActiveTexture(LOCAL_GL_TEXTURE2);
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[2].GetTextureID());
-    ApplyFilter(mFilter);
+    gl()->ApplyFilterToBoundTexture(mFilter);
     
     YCbCrTextureLayerProgram *program = mOGLManager->GetYCbCrLayerProgram();
 
     program->Activate();
     program->SetLayerQuadRect(nsIntRect(0, 0,
                                         yuvImage->mSize.width,
                                         yuvImage->mSize.height));
     program->SetLayerTransform(GetEffectiveTransform());
@@ -477,17 +477,17 @@ ImageLayerOGL::RenderLayer(int,
             sGLXLibrary.BindTexImage(pixmap);
         }
     }
 #endif
 
     ColorTextureLayerProgram *program = 
       mOGLManager->GetColorTextureLayerProgram(cairoImage->mLayerProgram);
 
-    ApplyFilter(mFilter);
+    gl()->ApplyFilterToBoundTexture(mFilter);
 
     program->Activate();
     // The following uniform controls the scaling of the vertex coords.
     // Instead of setting the scale here and using coords in the range [0,1], we
     // set an identity transform and use pixel coordinates below
     program->SetLayerQuadRect(nsIntRect(0, 0, 1, 1));
     program->SetLayerTransform(GetEffectiveTransform());
     program->SetLayerOpacity(GetEffectiveOpacity());
@@ -952,33 +952,33 @@ ShadowImageLayerOGL::RenderLayer(int aPr
       mOGLManager->GetColorTextureLayerProgram(mTexImage->GetShaderProgramType());
 
     colorProgram->Activate();
     colorProgram->SetTextureUnit(0);
     colorProgram->SetLayerTransform(GetEffectiveTransform());
     colorProgram->SetLayerOpacity(GetEffectiveOpacity());
     colorProgram->SetRenderOffset(aOffset);
 
+    mTexImage->SetFilter(mFilter);
     mTexImage->BeginTileIteration();
     do {
-      TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
-      ApplyFilter(mFilter);
+      TextureImage::ScopedBindTextureAndApplyFilter texBind(mTexImage, LOCAL_GL_TEXTURE0);
       colorProgram->SetLayerQuadRect(mTexImage->GetTileRect());
       mOGLManager->BindAndDrawQuad(colorProgram);
     } while (mTexImage->NextTile());
   } else {
     gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mYUVTexture[0].GetTextureID());
-    ApplyFilter(mFilter);
+    gl()->ApplyFilterToBoundTexture(mFilter);
     gl()->fActiveTexture(LOCAL_GL_TEXTURE1);
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mYUVTexture[1].GetTextureID());
-    ApplyFilter(mFilter);
+    gl()->ApplyFilterToBoundTexture(mFilter);
     gl()->fActiveTexture(LOCAL_GL_TEXTURE2);
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mYUVTexture[2].GetTextureID());
-    ApplyFilter(mFilter);
+    gl()->ApplyFilterToBoundTexture(mFilter);
 
     YCbCrTextureLayerProgram *yuvProgram = mOGLManager->GetYCbCrLayerProgram();
 
     yuvProgram->Activate();
     yuvProgram->SetLayerQuadRect(nsIntRect(0, 0,
                                            mPictureRect.width,
                                            mPictureRect.height));
     yuvProgram->SetYCbCrTextureUnits(0, 1, 2);
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -1161,31 +1161,16 @@ LayerManagerOGL::CreateFBOWithTexture(co
     mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
     mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
   }
 
   *aFBO = fbo;
   *aTexture = tex;
 }
 
-void 
-LayerOGL::ApplyFilter(gfxPattern::GraphicsFilter aFilter)
-{
-  if (aFilter == gfxPattern::FILTER_NEAREST) {
-    gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
-    gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
-  } else {
-    if (aFilter != gfxPattern::FILTER_GOOD) {
-      NS_WARNING("Unsupported filter type!");
-    }
-    gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
-    gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
-  }
-}
-
 already_AddRefed<ShadowThebesLayer>
 LayerManagerOGL::CreateShadowThebesLayer()
 {
   if (LayerManagerOGL::mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return nsnull;
   }
   return nsRefPtr<ShadowThebesLayerOGL>(new ShadowThebesLayerOGL(this)).forget();
--- a/gfx/layers/opengl/LayerManagerOGL.h
+++ b/gfx/layers/opengl/LayerManagerOGL.h
@@ -535,17 +535,16 @@ public:
   virtual void RenderLayer(int aPreviousFrameBuffer,
                            const nsIntPoint& aOffset) = 0;
 
   typedef mozilla::gl::GLContext GLContext;
 
   LayerManagerOGL* OGLManager() const { return mOGLManager; }
   GLContext *gl() const { return mOGLManager->gl(); }
 
-  void ApplyFilter(gfxPattern::GraphicsFilter aFilter);
 protected:
   LayerManagerOGL *mOGLManager;
   bool mDestroyed;
 };
 
 } /* layers */
 } /* mozilla */
 
--- a/gfx/thebes/GLContext.cpp
+++ b/gfx/thebes/GLContext.cpp
@@ -549,16 +549,30 @@ GLContext::CreateTextureImage(const nsIn
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, aWrapMode);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, aWrapMode);
 
     return CreateBasicTextureImage(texture, aSize, aWrapMode, aContentType, this);
 }
 
+void GLContext::ApplyFilterToBoundTexture(gfxPattern::GraphicsFilter aFilter)
+{
+    if (aFilter == gfxPattern::FILTER_NEAREST) {
+        fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
+        fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
+    } else {
+        if (aFilter != gfxPattern::FILTER_GOOD) {
+            NS_WARNING("Unsupported filter type!");
+        }
+        fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
+       fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
+    }
+}
+
 BasicTextureImage::~BasicTextureImage()
 {
     GLContext *ctx = mGLContext;
     if (ctx->IsDestroyed() || !NS_IsMainThread()) {
         ctx = ctx->GetSharedContext();
     }
 
     // If we have a context, then we need to delete the texture;
@@ -641,16 +655,23 @@ BasicTextureImage::EndUpdate()
 void
 BasicTextureImage::BindTexture(GLenum aTextureUnit)
 {
     mGLContext->fActiveTexture(aTextureUnit);
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
     mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
 }
 
+void
+BasicTextureImage::ApplyFilter()
+{
+  mGLContext->ApplyFilterToBoundTexture(mFilter);
+}
+
+
 already_AddRefed<gfxASurface>
 BasicTextureImage::GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt)
 {
     return gfxPlatform::GetPlatform()->
         CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFmt));
 }
 
 bool
@@ -923,16 +944,22 @@ nsIntRect TiledTextureImage::GetTileRect
 }
 
 void
 TiledTextureImage::BindTexture(GLenum aTextureUnit)
 {
     mImages[mCurrentImage]->BindTexture(aTextureUnit);
 }
 
+void
+TiledTextureImage::ApplyFilter()
+{
+   mGL->ApplyFilterToBoundTexture(mFilter);
+}
+
 /*
  * simple resize, just discards everything. we can be more clever just
  * adding or discarding tiles, but do we want this?
  */
 void TiledTextureImage::Resize(const nsIntSize& aSize)
 {
     if (mSize == aSize && mTextureState != Created) {
         return;
--- a/gfx/thebes/GLContext.h
+++ b/gfx/thebes/GLContext.h
@@ -252,16 +252,21 @@ public:
      * aRegion - the region in this image to update
      * aFrom - offset in the source to update from
      */
     virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0)) = 0;
 
     virtual void BindTexture(GLenum aTextureUnit) = 0;
     virtual void ReleaseTexture() {};
 
+    void BindTextureAndApplyFilter(GLenum aTextureUnit) {
+        BindTexture(aTextureUnit);
+        ApplyFilter();
+    }
+
     class ScopedBindTexture
     {
     public:
         ScopedBindTexture(TextureImage *aTexture, GLenum aTextureUnit) :
           mTexture(aTexture)
         {
             if (mTexture) {
                 mTexture->BindTexture(aTextureUnit);
@@ -270,20 +275,32 @@ public:
 
         ~ScopedBindTexture()
         {
             if (mTexture) {
                 mTexture->ReleaseTexture();
             }       
         }
 
-    private:
+    protected:
         TextureImage *mTexture;
     };
 
+    class ScopedBindTextureAndApplyFilter
+        : public ScopedBindTexture
+    {
+    public:
+        ScopedBindTextureAndApplyFilter(TextureImage *aTexture, GLenum aTextureUnit) :
+          ScopedBindTexture(aTexture, aTextureUnit)
+        {
+            if (mTexture) {
+                mTexture->ApplyFilter();
+            }
+        }
+    };
 
     /**
      * Returns the shader program type that should be used to render
      * this texture. Only valid after a matching BeginUpdate/EndUpdate
      * pair have been called.
      */
     virtual ShaderProgramType GetShaderProgramType()
     {
@@ -301,16 +318,18 @@ public:
 
     const nsIntSize& GetSize() const { return mSize; }
     ContentType GetContentType() const { return mContentType; }
     virtual bool InUpdate() const = 0;
     GLenum GetWrapMode() const { return mWrapMode; }
 
     bool IsRGB() const { return mIsRGBFormat; }
 
+    void SetFilter(gfxPattern::GraphicsFilter aFilter) { mFilter = aFilter; }
+
 protected:
     friend class GLContext;
 
     /**
      * After the ctor, the TextureImage is invalid.  Implementations
      * must allocate resources successfully before returning the new
      * TextureImage from GLContext::CreateTextureImage().  That is,
      * clients must not be given partially-constructed TextureImages.
@@ -319,21 +338,28 @@ protected:
                  GLenum aWrapMode, ContentType aContentType,
                  bool aIsRGB = false)
         : mSize(aSize)
         , mWrapMode(aWrapMode)
         , mContentType(aContentType)
         , mIsRGBFormat(aIsRGB)
     {}
 
+    /**
+     * Applies this TextureImage's filter, assuming that its texture is
+     * the currently bound texture.
+     */
+    virtual void ApplyFilter() = 0;
+
     nsIntSize mSize;
     GLenum mWrapMode;
     ContentType mContentType;
     bool mIsRGBFormat;
     ShaderProgramType mShaderType;
+    gfxPattern::GraphicsFilter mFilter;
 };
 
 /**
  * BasicTextureImage is the baseline TextureImage implementation ---
  * it updates its texture by allocating a scratch buffer for the
  * client to draw into, then using glTexSubImage2D() to upload the new
  * pixels.  Platforms must provide the code to create a new surface
  * into which the updated pixels will be drawn, and the code to
@@ -386,16 +412,18 @@ protected:
     GLuint mTexture;
     TextureState mTextureState;
     GLContext* mGLContext;
     nsRefPtr<gfxASurface> mUpdateSurface;
     nsIntRegion mUpdateRegion;
 
     // The offset into the update surface at which the update rect is located.
     nsIntPoint mUpdateOffset;
+
+    virtual void ApplyFilter();
 };
 
 /**
  * A container class that complements many sub TextureImages into a big TextureImage.
  * Aims to behave just like the real thing.
  */
 
 class TiledTextureImage
@@ -429,16 +457,18 @@ protected:
     unsigned int mRows, mColumns;
     GLContext* mGL;
     bool mUseNearestFilter;
     // A temporary surface to faciliate cross-tile updates.
     nsRefPtr<gfxASurface> mUpdateSurface;
     // The region of update requested
     nsIntRegion mUpdateRegion;
     TextureState mTextureState;
+
+    virtual void ApplyFilter();
 };
 
 struct THEBES_API ContextFormat
 {
     static const ContextFormat BasicRGBA32Format;
 
     enum StandardContextFormat {
         Empty,
@@ -655,16 +685,22 @@ public:
      * Defines a two-dimensional texture image for context target surface
      */
     virtual bool BindTexImage() { return false; }
     /*
      * Releases a color buffer that is being used as a texture
      */
     virtual bool ReleaseTexImage() { return false; }
 
+    /**
+     * Applies aFilter to the texture currently bound to GL_TEXTURE_2D.
+     */
+    void ApplyFilterToBoundTexture(gfxPattern::GraphicsFilter aFilter);
+
+
     /*
      * Offscreen support API
      */
 
     /*
      * Bind aOffscreen's color buffer as a texture to the TEXTURE_2D
      * target.  Returns TRUE on success, otherwise FALSE.  If
      * aOffscreen is not an offscreen context, returns FALSE.  If
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -1664,16 +1664,21 @@ protected:
     EGLSurface mSurface;
     EGLConfig mConfig;
     GLuint mTexture;
     EGLImageKHR mImageKHR;
     TextureState mTextureState;
 
     bool mBound;
     bool mIsLocked;
+
+    virtual void ApplyFilter()
+    {
+        mGLContext->ApplyFilterToBoundTexture(mFilter);
+    }
 };
 
 already_AddRefed<TextureImage>
 GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
                                  TextureImage::ContentType aContentType,
                                  GLenum aWrapMode,
                                  bool aUseNearestFilter)
 {
--- a/gfx/thebes/GLContextProviderGLX.cpp
+++ b/gfx/thebes/GLContextProviderGLX.cpp
@@ -911,16 +911,21 @@ private:
         }
     }
 
     GLContext* mGLContext;
     nsRefPtr<gfxASurface> mUpdateSurface;
     GLXPixmap mPixmap;
     bool mInUpdate;
     GLuint mTexture;
+
+    virtual void ApplyFilter()
+    {
+        mGLContext->ApplyFilterToBoundTexture(mFilter);
+    }
 };
 
 already_AddRefed<TextureImage>
 GLContextGLX::CreateTextureImage(const nsIntSize& aSize,
                                  TextureImage::ContentType aContentType,
                                  GLenum aWrapMode,
                                  bool aUseNearestFilter)
 {
new file mode 100644
--- /dev/null
+++ b/hal/Hal.cpp
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: sw=2 ts=8 et ft=cpp : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "Hal.h"
+#include "mozilla/Util.h"
+#include "nsThreadUtils.h"
+#include "nsXULAppAPI.h"
+
+#define PROXY_IF_SANDBOXED(_call)                 \
+  do {                                            \
+    if (InSandbox()) {                            \
+      hal_sandbox::_call;                         \
+    } else {                                      \
+      hal_impl::_call;                            \
+    }                                             \
+  } while (0)
+
+namespace mozilla {
+namespace hal {
+
+static void
+AssertMainThread()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+static bool
+InSandbox()
+{
+  return GeckoProcessType_Content == XRE_GetProcessType();
+}
+
+void
+Vibrate(const nsTArray<uint32>& pattern)
+{
+  AssertMainThread();
+  PROXY_IF_SANDBOXED(Vibrate(pattern));
+}
+
+} // namespace hal
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/hal/Hal.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: sw=2 ts=8 et ft=cpp : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_Hal_h
+#define mozilla_Hal_h 1
+
+#include "base/basictypes.h"
+#include "mozilla/Types.h"
+#include "nsTArray.h"
+
+#ifndef MOZ_HAL_NAMESPACE
+// This goop plays some cpp tricks to ensure a uniform API across the
+// API entry point, "sandbox" implementations (for content processes),
+// and "impl" backends where the real work happens.  After this runs
+// through cpp, there will be three sets of identical APIs
+//   hal_impl:: --- the platform-specific implementation of an API.
+//   hal_sandbox:: --- forwards calls up to the parent process
+//   hal:: --- invokes sandboxed impl if in a sandboxed process,
+//             otherwise forwards to hal_impl
+//
+// External code should never invoke hal_impl:: or hal_sandbox:: code
+// directly.
+# include "HalImpl.h"
+# include "HalSandbox.h"
+# define MOZ_HAL_NAMESPACE hal
+# define MOZ_DEFINED_HAL_NAMESPACE 1
+#endif
+
+namespace mozilla {
+namespace MOZ_HAL_NAMESPACE /*hal*/ {
+
+/**
+ * Turn the default vibrator device on/off per the pattern specified
+ * by |pattern|.  Each element in the pattern is the number of
+ * milliseconds to turn the vibrator on or off.  The first element in
+ * |pattern| is an "on" element, the next is "off", and so on.
+ *
+ * If |pattern| is empty, any in-progress vibration is canceled.
+ */
+void Vibrate(const nsTArray<uint32>& pattern);
+
+}
+}
+
+#ifdef MOZ_DEFINED_HAL_NAMESPACE
+# undef MOZ_DEFINED_HAL_NAMESPACE
+# undef MOZ_HAL_NAMESPACE
+#endif
+
+#endif  // mozilla_Hal_h
new file mode 100644
--- /dev/null
+++ b/hal/HalImpl.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: sw=2 ts=8 et ft=cpp : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_Hal_h
+# error "This is an internal file, don't include it"
+#endif
+
+#undef mozilla_Hal_h
+#define MOZ_HAL_NAMESPACE hal_impl
+#include "Hal.h"
+#undef MOZ_HAL_NAMESPACE
+
new file mode 100644
--- /dev/null
+++ b/hal/HalSandbox.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: sw=2 ts=8 et ft=cpp : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_Hal_h
+# error "This is an internal file, don't include it"
+#endif
+
+#undef mozilla_Hal_h
+#define MOZ_HAL_NAMESPACE hal_sandbox
+#include "Hal.h"
+#undef MOZ_HAL_NAMESPACE
new file mode 100644
--- /dev/null
+++ b/hal/Makefile.in
@@ -0,0 +1,71 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Corporation code.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Chris Jones <jones.chris.g@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of 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 *****
+
+DEPTH       = ..
+topsrcdir   = @top_srcdir@
+srcdir      = @srcdir@
+VPATH       = \
+  $(srcdir) \
+  $(srcdir)/fallback \
+  $(srcdir)/sandbox \
+  $(NULL)
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE         = hal
+LIBRARY_NAME   = hal_s
+FORCE_STATIC_LIB = 1
+LIBXUL_LIBRARY = 1
+EXPORT_LIBRARY = 1
+
+EXPORTS_NAMESPACES = mozilla
+EXPORTS_mozilla = \
+  Hal.h \
+  HalImpl.h \
+  HalSandbox.h \
+  $(NULL)
+
+CPPSRCS = \
+  Hal.cpp \
+  SandboxHal.cpp \
+  $(NULL)
+
+CPPSRCS += FallbackHal.cpp
+
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/hal/fallback/FallbackHal.cpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: sw=2 ts=8 et ft=cpp : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "Hal.h"
+
+namespace mozilla {
+namespace hal_impl {
+
+void
+Vibrate(const nsTArray<uint32>& pattern)
+{}
+
+} // hal_impl
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/hal/sandbox/PHal.ipdl
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: sw=2 ts=8 et ft=cpp : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+include protocol PContent;
+
+namespace mozilla {
+namespace hal_sandbox {
+
+protocol PHal {
+    manager PContent;
+
+parent:
+    Vibrate(uint32[] pattern);
+
+    __delete__();
+};
+
+} // namespace hal
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/hal/sandbox/SandboxHal.cpp
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: sw=2 ts=8 et ft=cpp : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "Hal.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/hal_sandbox/PHalChild.h"
+#include "mozilla/hal_sandbox/PHalParent.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+using namespace mozilla::hal;
+
+namespace mozilla {
+namespace hal_sandbox {
+
+static PHalChild* sHal;
+static PHalChild*
+Hal()
+{
+  if (!sHal) {
+    sHal = ContentChild::GetSingleton()->SendPHalConstructor();
+  }
+  return sHal;
+}
+
+void
+Vibrate(const nsTArray<uint32>& pattern)
+{
+  AutoInfallibleTArray<uint32, 8> p(pattern);
+  Hal()->SendVibrate(p);
+}
+
+class HalParent : public PHalParent {
+public:
+  NS_OVERRIDE virtual bool
+  RecvVibrate(const InfallibleTArray<unsigned int>& pattern) {
+    // Forward to hal::, not hal_impl::, because we might be a
+    // subprocess of another sandboxed process.  The hal:: entry point
+    // will do the right thing.
+    hal::Vibrate(pattern);
+    return true;
+  }
+};
+
+class HalChild : public PHalChild {
+public:
+};
+
+PHalChild* CreateHalChild() {
+  return new HalChild();
+}
+
+PHalParent* CreateHalParent() {
+  return new HalParent();
+}
+
+} // namespace hal_sandbox
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/hal/sandbox/SandboxHal.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: sw=2 ts=8 et ft=cpp : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_SandboxHal_h
+#define mozilla_SandboxHal_h
+
+namespace mozilla {
+namespace hal_sandbox {
+
+class PHalChild;
+class PHalParent;
+
+PHalChild* CreateHalChild();
+
+PHalParent* CreateHalParent();
+
+}
+}
+
+#endif  // mozilla_SandboxHal_h
new file mode 100644
--- /dev/null
+++ b/hal/sandbox/ipdl.mk
@@ -0,0 +1,39 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Content App.
+#
+# The Initial Developer of the Original Code is
+#   The Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# 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 *****
+
+IPDLSRCS = \
+  PHal.ipdl \
+  $(NULL)
--- a/ipc/ipdl/Makefile.in
+++ b/ipc/ipdl/Makefile.in
@@ -54,16 +54,17 @@ EXPORT_LIBRARY = 1
 ## When you add IPDL files to a source directory, list the directory here.
 ##
 IPDLDIRS =  \
   uriloader/exthandler \
   dom/plugins/ipc  \
   dom/ipc  \
   dom/src/storage \
   gfx/layers/ipc \
+  hal/sandbox \
   ipc/testshell  \
   js/ipc  \
   js/jetpack \
   layout/ipc \
   netwerk/ipc  \
   netwerk/protocol/ftp \
   netwerk/protocol/http  \
   netwerk/protocol/wyciwyg \
--- a/ipc/ipdl/ipdl/builtin.py
+++ b/ipc/ipdl/ipdl/builtin.py
@@ -70,17 +70,29 @@ Types = (
     'PRInt64',
     'PRUint64',
     'PRSize',
 
     # Mozilla types: "less" standard things we know how serialize/deserialize
     'nsresult',
     'nsString',
     'nsCString',
-    'mozilla::ipc::Shmem'
+    'mozilla::ipc::Shmem',
+
+    # quasi-stdint types used by "public" Gecko headers
+    'int8',
+    'uint8',
+    'int16',
+    'uint16',
+    'int32',
+    'uint32',
+    'int64',
+    'uint64',
+    'intptr',
+    'uintptr',
 )
 
 
 Includes = (
     'base/basictypes.h',
     'prtime.h',
     'nscore.h',
     'IPCMessageStart.h',
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug688939.js
@@ -0,0 +1,4 @@
+gczeal(2);
+string=""
+for (var i = 0; i < 100; i++ )
+  hex=newGlobal('same-compartment');
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1590,25 +1590,24 @@ js_XDRFunctionObject(JSXDRState *xdr, JS
         fun->flags = uint16(flagsword);
         fun->u.i.skipmin = uint16(firstword >> 2);
     }
 
     /*
      * Don't directly store into fun->u.i.script because we want this to happen
      * at the same time as we set the script's owner.
      */
-    JSScript *script = fun->u.i.script;
+    JSScript *script = fun->script();
     if (!js_XDRScript(xdr, &script))
         return false;
-    fun->u.i.script = script;
 
     if (xdr->mode == JSXDR_DECODE) {
         *objp = fun;
-        fun->u.i.script->setOwnerObject(fun);
-        if (!fun->u.i.script->typeSetFunction(cx, fun))
+        fun->setScript(script);
+        if (!fun->script()->typeSetFunction(cx, fun))
             return false;
         JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
         js_CallNewScriptHook(cx, fun->script(), fun);
     }
 
     return true;
 }
 
@@ -2347,17 +2346,17 @@ js_NewFunction(JSContext *cx, JSObject *
 
     /* Initialize all function members. */
     fun->nargs = uint16(nargs);
     fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK | JSFUN_TRCINFO);
     if ((flags & JSFUN_KINDMASK) >= JSFUN_INTERPRETED) {
         JS_ASSERT(!native);
         JS_ASSERT(nargs == 0);
         fun->u.i.skipmin = 0;
-        fun->u.i.script = NULL;
+        fun->u.i.script_ = NULL;
     } else {
         fun->u.n.clasp = NULL;
         if (flags & JSFUN_TRCINFO) {
 #ifdef JS_TRACER
             JSNativeTraceInfo *trcinfo =
                 JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, native);
             fun->u.n.native = (Native) trcinfo->native;
             fun->u.n.trcinfo = trcinfo;
@@ -2416,32 +2415,31 @@ js_CloneFunctionObject(JSContext *cx, JS
 
         JSFunction *cfun = (JSFunction *) clone;
         cfun->nargs = fun->nargs;
         cfun->flags = fun->flags;
         cfun->u = fun->getFunctionPrivate()->u;
         cfun->atom = fun->atom;
         clone->setPrivate(cfun);
         if (cfun->isInterpreted()) {
-            JSScript *script = cfun->script();
+            JSScript *script = fun->script();
             JS_ASSERT(script);
             JS_ASSERT(script->compartment() == fun->compartment());
             JS_ASSERT(script->compartment() != cx->compartment);
             JS_OPT_ASSERT(script->ownerObject == fun);
 
-            cfun->u.i.script = NULL;
+            cfun->u.i.script_ = NULL;
             JSScript *cscript = js_CloneScript(cx, script);
             if (!cscript)
                 return NULL;
 
-            cfun->u.i.script = cscript;
-            if (!cfun->u.i.script->typeSetFunction(cx, cfun))
+            cfun->setScript(cscript);
+            if (!cfun->script()->typeSetFunction(cx, cfun))
                 return NULL;
 
-            cfun->script()->setOwnerObject(cfun);
             js_CallNewScriptHook(cx, cfun->script(), cfun);
             Debugger::onNewScript(cx, cfun->script(), cfun, Debugger::NewHeldScript);
         }
     }
     return clone;
 }
 
 #ifdef JS_TRACER
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -110,19 +110,20 @@ struct JSFunction : public JSObject_Slot
     union U {
         struct {
             js::Native  native;   /* native method pointer or null */
             js::Class   *clasp;   /* class of objects constructed
                                      by this function */
             JSNativeTraceInfo *trcinfo;
         } n;
         struct Scripted {
-            JSScript    *script;  /* interpreted bytecode descriptor or null */
+            JSScript    *script_; /* interpreted bytecode descriptor or null;
+                                     use the setter! */
             uint16       skipmin; /* net skip amount up (toward zero) from
-                                     script->staticLevel to nearest upvar,
+                                     script_->staticLevel to nearest upvar,
                                      including upvars in nested functions */
             js::Shape   *names;   /* argument and variable names */
         } i;
         void            *nativeOrScript;
     } u;
     JSAtom          *atom;        /* name for diagnostics and decompiling */
 
     bool optimizedClosure()  const { return kind() > JSFUN_INTERPRETED; }
@@ -191,34 +192,40 @@ struct JSFunction : public JSObject_Slot
                ? &getSlot(METHOD_ATOM_SLOT).toString()->asAtom()
                : NULL;
     }
 
     inline void setMethodAtom(JSAtom *atom);
 
     JSScript *script() const {
         JS_ASSERT(isInterpreted());
-        return u.i.script;
+        return u.i.script_;
+    }
+
+    void setScript(JSScript *script) {
+        JS_ASSERT(isInterpreted());
+        u.i.script_ = script;
+        script->setOwnerObject(this);
     }
 
     JSScript * maybeScript() const {
         return isInterpreted() ? script() : NULL;
     }
 
     JSNative native() const {
         JS_ASSERT(isNative());
         return u.n.native;
     }
 
     JSNative maybeNative() const {
         return isInterpreted() ? NULL : native();
     }
 
     static uintN offsetOfNativeOrScript() {
-        JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, i.script));
+        JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, i.script_));
         JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, nativeOrScript));
         return offsetof(JSFunction, u.nativeOrScript);
     }
 
     /* Number of extra fixed function object slots. */
     static const uint32 CLASS_RESERVED_SLOTS = JSObject::FUN_CLASS_RESERVED_SLOTS;
 
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -883,18 +883,36 @@ MarkThreadDataConservatively(JSTracer *t
     MarkRangeConservatively(trc, stackMin, stackEnd);
     MarkRangeConservatively(trc, ctd->registerSnapshot.words,
                             JS_ARRAY_END(ctd->registerSnapshot.words));
 }
 
 void
 MarkStackRangeConservatively(JSTracer *trc, Value *beginv, Value *endv)
 {
+    /*
+     * Normally, the drainMarkStack phase of marking will never trace outside
+     * of the compartment currently being collected. However, conservative
+     * scanning during drainMarkStack (as is done for generators) can break
+     * this invariant. So we disable the compartment assertions in this
+     * situation.
+     */
+    struct AutoSkipChecking {
+        JSRuntime *runtime;
+        JSCompartment *savedCompartment;
+
+        AutoSkipChecking(JSRuntime *rt)
+          : runtime(rt), savedCompartment(rt->gcCheckCompartment) {
+            rt->gcCheckCompartment = NULL;
+        }
+        ~AutoSkipChecking() { runtime->gcCheckCompartment = savedCompartment; }
+    } as(trc->context->runtime);
+
     const jsuword *begin = beginv->payloadWord();
-    const jsuword *end = endv->payloadWord();;
+    const jsuword *end = endv->payloadWord();
 #ifdef JS_NUNBOX32
     /*
      * With 64-bit jsvals on 32-bit systems, we can optimize a bit by
      * scanning only the payloads.
      */
     JS_ASSERT(begin <= end);
     for (const jsuword *i = begin; i != end; i += sizeof(Value)/sizeof(jsuword))
         MarkWordConservatively(trc, *i);
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -383,40 +383,41 @@ TypeSet::add(JSContext *cx, TypeConstrai
 
     JS_ASSERT(constraint->next == NULL);
     constraint->next = constraintList;
     constraintList = constraint;
 
     if (!callExisting)
         return;
 
+    /* If any type is possible, there's no need to worry about specifics. */
     if (flags & TYPE_FLAG_UNKNOWN) {
         cx->compartment->types.addPending(cx, constraint, this, Type::UnknownType());
-        cx->compartment->types.resolvePending(cx);
-        return;
-    }
-
-    for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
-        if (flags & flag) {
-            Type type = Type::PrimitiveType(TypeFlagPrimitive(flag));
-            cx->compartment->types.addPending(cx, constraint, this, type);
+    } else {
+        /* Enqueue type set members stored as bits. */ 
+        for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
+            if (flags & flag) {
+                Type type = Type::PrimitiveType(TypeFlagPrimitive(flag));
+                cx->compartment->types.addPending(cx, constraint, this, type);
+            }
         }
-    }
-
-    if (flags & TYPE_FLAG_ANYOBJECT) {
-        cx->compartment->types.addPending(cx, constraint, this, Type::AnyObjectType());
-        cx->compartment->types.resolvePending(cx);
-        return;
-    }
-
-    unsigned count = getObjectCount();
-    for (unsigned i = 0; i < count; i++) {
-        TypeObjectKey *object = getObject(i);
-        if (object)
-            cx->compartment->types.addPending(cx, constraint, this, Type::ObjectType(object));
+
+        /* If any object is possible, skip specifics. */
+        if (flags & TYPE_FLAG_ANYOBJECT) {
+            cx->compartment->types.addPending(cx, constraint, this, Type::AnyObjectType());
+        } else {
+            /* Enqueue specific object types. */
+            unsigned count = getObjectCount();
+            for (unsigned i = 0; i < count; i++) {
+                TypeObjectKey *object = getObject(i);
+                if (object)
+                    cx->compartment->types.addPending(cx, constraint, this,
+                                                      Type::ObjectType(object));
+            }
+        }
     }
 
     cx->compartment->types.resolvePending(cx);
 }
 
 void
 TypeSet::print(JSContext *cx)
 {
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -3798,98 +3798,89 @@ BEGIN_CASE(JSOP_SETMETHOD)
     } while (0);
 }
 END_SET_CASE_STORE_RVAL(JSOP_SETPROP, 2);
 
 BEGIN_CASE(JSOP_GETELEM)
 {
     Value &lref = regs.sp[-2];
     Value &rref = regs.sp[-1];
+    Value &rval = regs.sp[-2];
     if (lref.isString() && rref.isInt32()) {
         JSString *str = lref.toString();
         int32_t i = rref.toInt32();
         if (size_t(i) < str->length()) {
             str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(i));
             if (!str)
                 goto error;
+            rval.setString(str);
+            TypeScript::Monitor(cx, script, regs.pc, rval);
             regs.sp--;
-            regs.sp[-1].setString(str);
-            TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
             len = JSOP_GETELEM_LENGTH;
             DO_NEXT_OP(len);
         }
     }
 
     if (lref.isMagic(JS_LAZY_ARGUMENTS)) {
         if (rref.isInt32() && size_t(rref.toInt32()) < regs.fp()->numActualArgs()) {
+            rval = regs.fp()->canonicalActualArg(rref.toInt32());
+            TypeScript::Monitor(cx, script, regs.pc, rval);
             regs.sp--;
-            regs.sp[-1] = regs.fp()->canonicalActualArg(rref.toInt32());
-            TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
             len = JSOP_GETELEM_LENGTH;
             DO_NEXT_OP(len);
         }
         MarkArgumentsCreated(cx, script);
         JS_ASSERT(!lref.isMagic(JS_LAZY_ARGUMENTS));
     }
 
     JSObject *obj;
     VALUE_TO_OBJECT(cx, &lref, obj);
 
-    const Value *copyFrom;
-    Value rval;
-    jsid id;
-    if (rref.isInt32()) {
-        int32_t i = rref.toInt32();
+    uint32 index;
+    if (IsDefinitelyIndex(rref, &index)) {
         if (obj->isDenseArray()) {
-            jsuint idx = jsuint(i);
-            if (idx < obj->getDenseArrayInitializedLength()) {
-                copyFrom = &obj->getDenseArrayElement(idx);
-                if (!copyFrom->isMagic())
+            if (index < obj->getDenseArrayInitializedLength()) {
+                rval = obj->getDenseArrayElement(index);
+                if (!rval.isMagic())
                     goto end_getelem;
             }
         } else if (obj->isArguments()) {
-            uint32 arg = uint32(i);
-            ArgumentsObject *argsobj = obj->asArguments();
-
-            if (arg < argsobj->initialLength()) {
-                copyFrom = &argsobj->element(arg);
-                if (!copyFrom->isMagic(JS_ARGS_HOLE)) {
-                    if (StackFrame *afp = argsobj->maybeStackFrame())
-                        copyFrom = &afp->canonicalActualArg(arg);
-                    goto end_getelem;
-                }
+            if (obj->asArguments()->getElement(index, &rval))
+                goto end_getelem;
+        }
+
+        if (!obj->getElement(cx, index, &rval))
+            goto error;
+    } else {
+        if (script->hasAnalysis() && !regs.fp()->hasImacropc())
+            script->analysis()->getCode(regs.pc).getStringElement = true;
+
+        SpecialId special;
+        if (ValueIsSpecial(obj, &rref, &special, cx)) {
+            if (!obj->getSpecial(cx, special, &rval))
+                goto error;
+        } else {
+            JSAtom *name;
+            if (!js_ValueToAtom(cx, rref, &name))
+                goto error;
+
+            if (name->isIndex(&index)) {
+                if (!obj->getElement(cx, index, &rval))
+                    goto error;
+            } else {
+                if (!obj->getProperty(cx, name->asPropertyName(), &rval))
+                    goto error;
             }
         }
-        if (JS_LIKELY(INT_FITS_IN_JSID(i)))
-            id = INT_TO_JSID(i);
-        else
-            goto intern_big_int;
-    } else {
-        int32_t i;
-        if (ValueFitsInInt32(rref, &i) && INT_FITS_IN_JSID(i)) {
-            id = INT_TO_JSID(i);
-        } else {
-          intern_big_int:
-            if (!js_InternNonIntElementId(cx, obj, rref, &id))
-                goto error;
-        }
     }
 
-    if (JSID_IS_STRING(id) && script->hasAnalysis() && !regs.fp()->hasImacropc())
-        script->analysis()->getCode(regs.pc).getStringElement = true;
-
-    if (!obj->getGeneric(cx, id, &rval))
-        goto error;
-    copyFrom = &rval;
-
   end_getelem:
+    assertSameCompartment(cx, rval);
+    TypeScript::Monitor(cx, script, regs.pc, rval);
     regs.sp--;
-    regs.sp[-1] = *copyFrom;
-    assertSameCompartment(cx, regs.sp[-1]);
-    TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
 }
 END_CASE(JSOP_GETELEM)
 
 BEGIN_CASE(JSOP_CALLELEM)
 {
     /* Find the object on which to look for |this|'s properties. */
     Value thisv = regs.sp[-2];
     JSObject *thisObj = ValuePropertyBearer(cx, thisv, -2);
--- a/js/src/jsnum.h
+++ b/js/src/jsnum.h
@@ -608,16 +608,42 @@ ValueFitsInInt32(const Value &v, int32_t
 {
     if (v.isInt32()) {
         *pi = v.toInt32();
         return true;
     }
     return v.isDouble() && JSDOUBLE_IS_INT32(v.toDouble(), pi);
 }
 
+/*
+ * Returns true if the given value is definitely an index: that is, the value
+ * is a number that's an unsigned 32-bit integer.
+ *
+ * This method prioritizes common-case speed over accuracy in every case.  It
+ * can produce false negatives (but not false positives): some values which are
+ * indexes will be reported not to be indexes by this method.  Users must
+ * consider this possibility when using this method.
+ */
+static JS_ALWAYS_INLINE bool
+IsDefinitelyIndex(const Value &v, uint32 *indexp)
+{
+    if (v.isInt32() && v.toInt32() >= 0) {
+        *indexp = v.toInt32();
+        return true;
+    }
+
+    int32 i;
+    if (v.isDouble() && JSDOUBLE_IS_INT32(v.toDouble(), &i) && i >= 0) {
+        *indexp = uint32(i);
+        return true;
+    }
+
+    return false;
+}
+
 /* ES5 9.4 ToInteger. */
 static inline bool
 ToInteger(JSContext *cx, const js::Value &v, jsdouble *dp)
 {
     if (v.isInt32()) {
         *dp = v.toInt32();
         return true;
     }
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1779,16 +1779,39 @@ ObjectClassIs(JSObject &obj, ESClassValu
       case ESClass_Number: return obj.isNumber();
       case ESClass_String: return obj.isString();
       case ESClass_Boolean: return obj.isBoolean();
     }
     JS_NOT_REACHED("bad classValue");
     return false;
 }
 
+static JS_ALWAYS_INLINE bool
+ValueIsSpecial(JSObject *obj, Value *propval, SpecialId *sidp, JSContext *cx)
+{
+    if (!propval->isObject())
+        return false;
+
+#if JS_HAS_XML_SUPPORT
+    if (obj->isXML()) {
+        *sidp = SpecialId(propval->toObject());
+        return true;
+    }
+
+    JSObject &propobj = propval->toObject();
+    JSAtom *name;
+    if (propobj.isQName() && GetLocalNameFromFunctionQName(&propobj, &name, cx)) {
+        propval->setString(name);
+        return false;
+    }
+#endif
+
+    return false;
+}
+
 } /* namespace js */
 
 inline JSObject *
 js_GetProtoIfDenseArray(JSObject *obj)
 {
     return obj->isDenseArray() ? obj->getProto() : obj;
 }
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1210,17 +1210,17 @@ JSScript::NewScriptFromCG(JSContext *cx,
                script->nClosedVars * sizeof(uint32));
     }
 
     script->bindings.transfer(cx, &cg->bindings);
 
     fun = NULL;
     if (cg->inFunction()) {
         /*
-         * We initialize fun->u.i.script to be the script constructed above
+         * We initialize fun->script() to be the script constructed above
          * so that the debugger has a valid fun->script().
          */
         fun = cg->fun();
         JS_ASSERT(fun->isInterpreted());
         JS_ASSERT(!fun->script());
 #ifdef DEBUG
         if (JSScript::isValidOffset(script->upvarsOffset))
             JS_ASSERT(script->upvars()->length == script->bindings.countUpvars());
@@ -1233,18 +1233,17 @@ JSScript::NewScriptFromCG(JSContext *cx,
         /* Watch for scripts whose functions will not be cloned. These are singletons. */
         bool singleton =
             cx->typeInferenceEnabled() && cg->parent && cg->parent->compiling() &&
             cg->parent->asCodeGenerator()->checkSingletonContext();
 
         if (!script->typeSetFunction(cx, fun, singleton))
             return NULL;
 
-        fun->u.i.script = script;
-        script->setOwnerObject(fun);
+        fun->setScript(script);
     } else {
         /*
          * Initialize script->object, if necessary, so that the debugger has a
          * valid holder object.
          */
         if ((cg->flags & TCF_NEED_SCRIPT_OBJECT) && !js_NewScriptObject(cx, script))
             return NULL;
     }
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -2803,34 +2803,43 @@ ToAttributeName(JSContext *cx, jsval v)
 }
 
 static void
 ReportBadXMLName(JSContext *cx, const Value &idval)
 {
     js_ReportValueError(cx, JSMSG_BAD_XML_NAME, JSDVG_IGNORE_STACK, idval, NULL);
 }
 
-static bool
-GetLocalNameFromFunctionQName(JSObject *qn, jsid *funidp, JSContext *cx)
+namespace js {
+
+bool
+GetLocalNameFromFunctionQName(JSObject *qn, JSAtom **namep, JSContext *cx)
 {
     JSAtom *atom = cx->runtime->atomState.functionNamespaceURIAtom;
     JSLinearString *uri = qn->getNameURI();
     if (uri && (uri == atom || EqualStrings(uri, atom))) {
-        *funidp = ATOM_TO_JSID(qn->getQNameLocalName());
+        *namep = qn->getQNameLocalName();
         return true;
     }
     return false;
 }
 
+} /* namespace js */
+
 bool
 js_GetLocalNameFromFunctionQName(JSObject *obj, jsid *funidp, JSContext *cx)
 {
     if (!obj->isQName())
         return false;
-    return GetLocalNameFromFunctionQName(obj, funidp, cx);
+    JSAtom *name;
+    if (GetLocalNameFromFunctionQName(obj, &name, cx)) {
+        *funidp = ATOM_TO_JSID(name);
+        return true;
+    }
+    return false;
 }
 
 static JSObject *
 ToXMLName(JSContext *cx, jsval v, jsid *funidp)
 {
     JSAtom *atomizedName;
     JSString *name;
     JSObject *obj;
@@ -2888,18 +2897,20 @@ ToXMLName(JSContext *cx, jsval v, jsid *
 
 construct:
     v = STRING_TO_JSVAL(name);
     obj = js_ConstructObject(cx, &QNameClass, NULL, NULL, 1, &v);
     if (!obj)
         return NULL;
 
 out:
-    if (!GetLocalNameFromFunctionQName(obj, funidp, cx))
-        *funidp = JSID_VOID;
+    JSAtom *localName;
+    *funidp = GetLocalNameFromFunctionQName(obj, &localName, cx)
+              ? ATOM_TO_JSID(localName)
+              : JSID_VOID;
     return obj;
 
 bad:
     JSAutoByteString bytes;
     if (js_ValueToPrintable(cx, StringValue(name), &bytes))
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_XML_NAME, bytes.ptr());
     return NULL;
 }
@@ -7613,18 +7624,21 @@ js_FindXMLProperty(JSContext *cx, const 
         if (!nameobj)
             return JS_FALSE;
     } else {
         JS_ASSERT(nameobj->getClass() == &AttributeNameClass ||
                   nameobj->getClass() == &QNameClass);
     }
 
     qn = nameobj;
-    if (!GetLocalNameFromFunctionQName(qn, &funid, cx))
-        funid = JSID_VOID;
+
+    JSAtom *name;
+    funid = GetLocalNameFromFunctionQName(qn, &name, cx)
+            ? ATOM_TO_JSID(name)
+            : JSID_VOID;
 
     obj = cx->stack.currentScriptedScopeChain();
     do {
         /* Skip any With object that can wrap XML. */
         target = obj;
         while (target->getClass() == &WithClass) {
              proto = target->getProto();
              if (!proto)
--- a/js/src/jsxml.h
+++ b/js/src/jsxml.h
@@ -327,9 +327,16 @@ js_MakeXMLPIString(JSContext *cx, JSStri
 /* The caller must ensure that either v1 or v2 is an object. */
 extern JSBool
 js_TestXMLEquality(JSContext *cx, const js::Value &v1, const js::Value &v2,
                    JSBool *bp);
 
 extern JSBool
 js_ConcatenateXML(JSContext *cx, JSObject *obj1, JSObject *obj2, js::Value *vp);
 
+namespace js {
+
+extern bool
+GetLocalNameFromFunctionQName(JSObject *qn, JSAtom **namep, JSContext *cx);
+
+} /* namespace js */
+
 #endif /* jsxml_h___ */
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -729,17 +729,17 @@ class CallCompiler : public BaseCompiler
         RegisterID t0 = inlFrame.tempRegs.takeAnyReg().reg();
 
         /* Generate the inline frame creation. */
         void *ncode = ic.funGuard.labelAtOffset(ic.joinPointOffset).executableAddress();
         inlFrame.assemble(ncode, f.pc());
 
         /* funPtrReg is still valid. Check if a compilation is needed. */
         Address scriptAddr(ic.funPtrReg, offsetof(JSFunction, u) +
-                           offsetof(JSFunction::U::Scripted, script));
+                           offsetof(JSFunction::U::Scripted, script_));
         masm.loadPtr(scriptAddr, t0);
 
         /*
          * Test if script->nmap is NULL - same as checking ncode, but faster
          * here since ncode has two failure modes and we need to load out of
          * nmap anyway.
          */
         size_t offset = callingNew
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -428,89 +428,76 @@ stubs::GetGlobalName(VMFrame &f)
 void JS_FASTCALL
 stubs::GetElem(VMFrame &f)
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
     Value &lref = regs.sp[-2];
     Value &rref = regs.sp[-1];
+    Value &rval = regs.sp[-2];
     if (lref.isString() && rref.isInt32()) {
         JSString *str = lref.toString();
         int32_t i = rref.toInt32();
         if ((size_t)i < str->length()) {
             str = f.cx->runtime->staticStrings.getUnitStringForElement(cx, str, (size_t)i);
             if (!str)
                 THROW();
-            f.regs.sp[-2].setString(str);
+            rval.setString(str);
             return;
         }
     }
 
     if (lref.isMagic(JS_LAZY_ARGUMENTS)) {
         if (rref.isInt32() && size_t(rref.toInt32()) < regs.fp()->numActualArgs()) {
-            regs.sp[-2] = regs.fp()->canonicalActualArg(rref.toInt32());
+            rval = regs.fp()->canonicalActualArg(rref.toInt32());
             return;
         }
         MarkArgumentsCreated(cx, f.script());
         JS_ASSERT(!lref.isMagic(JS_LAZY_ARGUMENTS));
     }
 
     JSObject *obj = ValueToObject(cx, &lref);
     if (!obj)
         THROW();
 
-    const Value *copyFrom;
-    Value rval;
-    jsid id;
-    if (rref.isInt32()) {
-        int32_t i = rref.toInt32();
+    uint32 index;
+    if (IsDefinitelyIndex(rref, &index)) {
         if (obj->isDenseArray()) {
-            jsuint idx = jsuint(i);
-
-            if (idx < obj->getDenseArrayInitializedLength()) {
-                copyFrom = &obj->getDenseArrayElement(idx);
-                if (!copyFrom->isMagic())
-                    goto end_getelem;
+            if (index < obj->getDenseArrayInitializedLength()) {
+                rval = obj->getDenseArrayElement(index);
+                if (!rval.isMagic())
+                    return;
             }
         } else if (obj->isArguments()) {
-            uint32 arg = uint32(i);
-            ArgumentsObject *argsobj = obj->asArguments();
+            if (obj->asArguments()->getElement(index, &rval))
+                return;
+        }
 
-            if (arg < argsobj->initialLength()) {
-                copyFrom = &argsobj->element(arg);
-                if (!copyFrom->isMagic()) {
-                    if (StackFrame *afp = argsobj->maybeStackFrame())
-                        copyFrom = &afp->canonicalActualArg(arg);
-                    goto end_getelem;
-                }
+        if (!obj->getElement(cx, index, &rval))
+            THROW();
+    } else {
+        SpecialId special;
+        if (ValueIsSpecial(obj, &rref, &special, cx)) {
+            if (!obj->getSpecial(cx, special, &rval))
+                THROW();
+        } else {
+            JSAtom *name;
+            if (!js_ValueToAtom(cx, rref, &name))
+                THROW();
+
+            if (name->isIndex(&index)) {
+                if (!obj->getElement(cx, index, &rval))
+                    THROW();
+            } else {
+                if (!obj->getProperty(cx, name->asPropertyName(), &rval))
+                    THROW();
             }
         }
-        if (JS_LIKELY(INT_FITS_IN_JSID(i)))
-            id = INT_TO_JSID(i);
-        else
-            goto intern_big_int;
-
-    } else {
-        int32_t i;
-        if (ValueFitsInInt32(rref, &i) && INT_FITS_IN_JSID(i)) {
-            id = INT_TO_JSID(i);
-        } else {
-          intern_big_int:
-            if (!js_InternNonIntElementId(cx, obj, rref, &id))
-                THROW();
-        }
     }
-
-    if (!obj->getGeneric(cx, id, &rval))
-        THROW();
-    copyFrom = &rval;
-
-  end_getelem:
-    f.regs.sp[-2] = *copyFrom;
 }
 
 static inline bool
 FetchElementId(VMFrame &f, JSObject *obj, const Value &idval, jsid &id, Value *vp)
 {
     int32_t i_;
     if (ValueFitsInInt32(idval, &i_) && INT_FITS_IN_JSID(i_)) {
         id = INT_TO_JSID(i_);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2731,17 +2731,17 @@ Clone(JSContext *cx, uintN argc, jsval *
             JSFunction *fun = JS_ValueToFunction(cx, argv[0]);
             if (!fun)
                 return JS_FALSE;
             funobj = JS_GetFunctionObject(fun);
         }
     }
     if (funobj->compartment() != cx->compartment) {
         JSFunction *fun = funobj->getFunctionPrivate();
-        if (fun->isInterpreted() && fun->u.i.script->compileAndGo) {
+        if (fun->isInterpreted() && fun->script()->compileAndGo) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
                                  "function", "compile-and-go");
             return JS_FALSE;
         }
     }
 
     if (argc > 1) {
         if (!JS_ValueToObject(cx, argv[1], &parent))
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -136,20 +136,19 @@ GlobalObject::initFunctionAndObjectClass
 
         JSScript *script =
             JSScript::NewScript(cx, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, JSVERSION_DEFAULT);
         if (!script)
             return NULL;
         script->noScriptRval = true;
         script->code[0] = JSOP_STOP;
         script->code[1] = SRC_NULL;
-        functionProto->u.i.script = script;
+        functionProto->setScript(script);
         functionProto->getType(cx)->interpretedFunction = functionProto;
         script->hasFunction = true;
-        script->setOwnerObject(functionProto);
     }
 
     /* Create the Object function now that we have a [[Prototype]] for it. */
     jsid objectId = ATOM_TO_JSID(CLASS_ATOM(cx, Object));
     JSFunction *objectCtor;
     {
         JSObject *ctor = NewObject<WithProto::Given>(cx, &FunctionClass, functionProto, this);
         if (!ctor)
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/691571-1-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="A" width=200 height=50></canvas><br />
+<canvas id="B" width=200 height=50></canvas>
+<script>
+  var canvasA = document.getElementById("A"),
+    ctxA = canvasA.getContext('2d'),
+    canvasB = document.getElementById("B"),
+    ctxB = canvasB.getContext('2d'),
+    width = canvasA.width,
+    height = canvasA.height;
+
+  ctxB.fillStyle = 'red';
+  ctxB.fillRect(0, 0, width, height);
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/691571-1.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="A" width=200 height=50></canvas><br />
+<canvas id="B" width=200 height=50></canvas>
+<script>
+  var canvasA = document.getElementById("A"),
+    ctxA = canvasA.getContext('2d'),
+    canvasB = document.getElementById("B"),
+    ctxB = canvasB.getContext('2d'),
+    width = canvasA.width,
+    height = canvasA.height;
+
+  ctxA.fillStyle = 'red';
+  ctxA.fillRect(0, 0, width, height);
+  var pat = ctxB.createPattern(canvasA, "repeat");
+
+  ctxA.clearRect(0, 0, width, height);
+
+  ctxB.fillStyle = pat;
+  ctxB.fillRect(0, 0, width, height);
+</script>
+</body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1661,8 +1661,9 @@ fails-if(layersGPUAccelerated&&cocoaWidg
 == 660682-1.html 660682-1-ref.html
 == 665597-1.html 665597-1-ref.html
 != 669015-1.xul 669015-1-notref.xul
 == 668319-1.xul about:blank
 == 670442-1.html 670442-1-ref.html
 == 670467-1.html 670467-1-ref.html
 == 670467-2.html 670467-2-ref.html
 != 691087-1.html 691087-1-ref.html
+== 691571-1.html 691571-1-ref.html
--- a/memory/jemalloc/jemalloc.c
+++ b/memory/jemalloc/jemalloc.c
@@ -77,16 +77,20 @@
  *   |                           | 1020 kB |
  *   |=====================================|
  *   | Huge                      |    1 MB |
  *   |                           |    2 MB |
  *   |                           |    3 MB |
  *   |                           |     ... |
  *   |=====================================|
  *
+ * NOTE: Due to Mozilla bug 691003, we cannot reserve less than one word for an
+ * allocation on Linux or Mac.  So on 32-bit *nix, the smallest bucket size is
+ * 4 bytes, and on 64-bit, the smallest bucket size is 8 bytes.
+ *
  * A different mechanism is used for each category:
  *
  *   Small : Each size class is segregated into its own set of runs.  Each run
  *           maintains a bitmap of which regions are free/allocated.
  *
  *   Large : Each allocation is backed by a dedicated run.  Metadata are stored
  *           in the associated arena chunk header maps.
  *
@@ -421,17 +425,17 @@ static const bool __isthreaded = true;
 #endif
 
 #  define inline
 #endif
 
 /* Size of stack-allocated buffer passed to strerror_r(). */
 #define	STRERROR_BUF		64
 
-/* Minimum alignment of allocations is 2^QUANTUM_2POW_MIN bytes. */
+/* Minimum alignment of non-tiny allocations is 2^QUANTUM_2POW_MIN bytes. */
 #  define QUANTUM_2POW_MIN      4
 #ifdef MOZ_MEMORY_SIZEOF_PTR_2POW
 #  define SIZEOF_PTR_2POW		MOZ_MEMORY_SIZEOF_PTR_2POW
 #else
 #  define SIZEOF_PTR_2POW       2
 #endif
 #define PIC
 #ifndef MOZ_MEMORY_DARWIN
@@ -510,18 +514,25 @@ static const bool __isthreaded = true;
 /*
  * Maximum size of L1 cache line.  This is used to avoid cache line aliasing,
  * so over-estimates are okay (up to a point), but under-estimates will
  * negatively affect performance.
  */
 #define	CACHELINE_2POW		6
 #define	CACHELINE		((size_t)(1U << CACHELINE_2POW))
 
-/* Smallest size class to support. */
+/*
+ * Smallest size class to support.  On Linux and Mac, even malloc(1) must
+ * reserve a word's worth of memory (see Mozilla bug 691003).
+ */
+#ifdef MOZ_MEMORY_WINDOWS
 #define	TINY_MIN_2POW		1
+#else
+#define TINY_MIN_2POW           (sizeof(void*) == 8 ? 3 : 2)
+#endif
 
 /*
  * Maximum size class that is a multiple of the quantum, but not (necessarily)
  * a power of 2.  Above this size, allocations are rounded up to the nearest
  * power of 2.
  */
 #define	SMALL_MAX_2POW_DEFAULT	9
 #define	SMALL_MAX_DEFAULT	(1U << SMALL_MAX_2POW_DEFAULT)
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -58,16 +58,17 @@ Cu.import("resource://gre/modules/AddonM
 /**
  * Cache of commonly used elements.
  */
 let Elements = {};
 
 [
   ["contentShowing",     "bcast_contentShowing"],
   ["urlbarState",        "bcast_urlbarState"],
+  ["mainKeyset",         "mainKeyset"],
   ["stack",              "stack"],
   ["tabList",            "tabs"],
   ["tabs",               "tabs-container"],
   ["controls",           "browser-controls"],
   ["panelUI",            "panel-container"],
   ["toolbarContainer",   "toolbar-container"],
   ["browsers",           "browsers"],
   ["contentViewport",    "content-viewport"],
@@ -940,19 +941,19 @@ var BrowserUI = {
         }
         break;
       }
       case "SizeChanged":
         this.sizeControls(ViewableAreaObserver.width, ViewableAreaObserver.height);
         break;
       // Window events
       case "keypress":
-        // Ignore events headed toward the browser; they will be
-        // re-dispatched after content has a chance to handle them.
-        if (aEvent.target.localName == "browser")
+        // Ignore events re-dispatched from content; we already
+        // handled them when they were originally fired.
+        if (aEvent.target == Elements.mainKeyset)
           break;
         if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE)
           this.handleEscape(aEvent);
         break;
       case "AppCommand":
         aEvent.stopPropagation();
         switch (aEvent.command) {
           case "Menu":
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1231,17 +1231,17 @@ var Browser = {
         setTimeout(function(self) {
           let tab = self.getTabForBrowser(browser);
           self._doCloseTab(tab);
         }, 0, this);
         break;
       }
 
       case "Browser:KeyPress": {
-        let keyset = document.getElementById("mainKeyset");
+        let keyset = Elements.mainKeyset;
         keyset.setAttribute("disabled", "false");
         if (json.preventDefault)
           break;
 
         let event = document.createEvent("KeyEvents");
         event.initKeyEvent("keypress", true, true, null,
                            json.ctrlKey, json.altKey, json.shiftKey, json.metaKey,
                            json.keyCode, json.charCode);
--- a/mobile/chrome/tests/browser_escape.js
+++ b/mobile/chrome/tests/browser_escape.js
@@ -96,16 +96,30 @@ function testGoBack() {
 
 function testReturnToOwner() {
   tab1 = Browser.addTab("about:blank", true);
   tab2 = Browser.addTab("about:blank", true, tab1);
   is(Browser.selectedTab, tab2, "tab2 is selected");
   EventUtils.sendKey("ESCAPE", window);
   is(Browser.selectedTab, tab1, "tab1 is selected");
   closeTabs();
+  testContextMenu();
+}
+
+function testContextMenu() {
+  ContextHelper.showPopup({
+    json: {
+      types: ['link']
+    },
+    target: Browser.selectedBrowser
+  });
+  ok(ContextHelper.popupState, "Context menu is shown");
+  Browser.selectedBrowser.focus();
+  EventUtils.synthesizeKey("VK_ESCAPE", {type: "keypress"}, window);
+  ok(!ContextHelper.popupState, "Context menu is dismissed");
   finish();
 }
 
 function closeTabs() {
   try {
     Browser.closeTab(tab1);
     Browser.closeTab(tab2);
   } finally {
--- a/toolkit/content/widgets/datetimepicker.xml
+++ b/toolkit/content/widgets/datetimepicker.xml
@@ -786,29 +786,35 @@
               return aNoWrap ? max : min;
             return aValue;
           ]]>
         </body>
       </method>
       <method name="_init">
         <body>
           <![CDATA[
+            // We'll default to YYYY/MM/DD to start.
+            var yfield = "input-one";
+            var mfield = "input-two";
+            var dfield = "input-three";
+            var twoDigitYear = false;
+            this.yearLeadingZero = true;
+            this.monthLeadingZero = true;
+            this.dateLeadingZero = true;
+
             var numberOrder = /^(\D*)\s*(\d+)(\D*)(\d+)(\D*)(\d+)\s*(\D*)$/;
 
             var dt = new Date(2002,9,4).toLocaleFormat("%x");
             var numberFields = dt.match(numberOrder);
             if (numberFields) {
               this._separatorFirst.value = numberFields[3];
               this._separatorSecond.value = numberFields[5];
 
-              var twoDigitYear = false;
-              var yfield = "input-one";
-              var mfield = "input-two";
-              var dfield = "input-three";
               var yi = 2, mi = 4, di = 6;
+
               for (var i = 1; i < numberFields.length; i++) {
                 switch (Number(numberFields[i])) {
                   case 2:
                     twoDigitYear = true; // fall through
                   case 2002:
                     yi = i;
                     yfield = (i == 2 ? "input-one" :
                              (i == 4 ? "input-two" : "input-three"));
@@ -820,29 +826,29 @@
                     break;
                   case 4:
                     di = i;
                     dfield = (i == 2 ? "input-one" :
                              (i == 4 ? "input-two" : "input-three"));
                     break;
                 }
               }
+
+              this.yearLeadingZero = (numberFields[yi].length > 1);
+              this.monthLeadingZero = (numberFields[mi].length > 1);
+              this.dateLeadingZero = (numberFields[di].length > 1);
             }
 
             this.yearField = document.getAnonymousElementByAttribute(this, "anonid", yfield);
             if (!twoDigitYear)
               this.yearField.parentNode.className =
                 "datetimepicker-input-subbox datetimepicker-year";
             this.monthField = document.getAnonymousElementByAttribute(this, "anonid", mfield);
             this.dateField = document.getAnonymousElementByAttribute(this, "anonid", dfield);
 
-            this.yearLeadingZero = (numberFields[yi].length > 1);
-            this.monthLeadingZero = (numberFields[mi].length > 1);
-            this.dateLeadingZero = (numberFields[di].length > 1);
-
             this._fieldAMPM.parentNode.collapsed = true;
             this.yearField.size = twoDigitYear ? 2 : 4;
             this.yearField.maxLength = twoDigitYear ? 2 : 4;
           ]]>
         </body>
       </method>
     </implementation>
 
--- a/toolkit/content/widgets/notification.xml
+++ b/toolkit/content/widgets/notification.xml
@@ -7,17 +7,18 @@
 
 <bindings id="notificationBindings"
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xbl="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="notificationbox">
     <content>
-      <xul:stack xbl:inherits="hidden=notificationshidden">
+      <xul:stack xbl:inherits="hidden=notificationshidden"
+                 class="notificationbox-stack">
         <xul:spacer/>
         <children includes="notification"/>
       </xul:stack>
       <children/>
     </content>
 
     <implementation>
       <field name="PRIORITY_INFO_LOW" readonly="true">1</field>
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -186,16 +186,20 @@ iframe {
 
 /********** notifications **********/
 
 notificationbox {
   -moz-binding: url("chrome://global/content/bindings/notification.xml#notificationbox");
   -moz-box-orient: vertical;
 }
 
+.notificationbox-stack {
+  overflow: -moz-hidden-unscrollable;
+}
+
 notification {
   -moz-binding: url("chrome://global/content/bindings/notification.xml#notification");
   -moz-transition: margin-top 300ms, opacity 300ms;
 }
 
 /*********** popup notification ************/
 popupnotification {
   -moz-binding: url("chrome://global/content/bindings/notification.xml#popup-notification")
--- a/toolkit/library/libxul-config.mk
+++ b/toolkit/library/libxul-config.mk
@@ -91,16 +91,17 @@ STATIC_LIBS += \
   jsipc_s \
   domipc_s \
   domplugins_s \
   mozipc_s \
   mozipdlgen_s \
   ipcshell_s \
   gfx2d \
   gfxipc_s \
+  hal_s \
   $(NULL)
 
 ifdef MOZ_IPDL_TESTS
 STATIC_LIBS += ipdlunittest_s
 endif
 
 ifeq (Linux,$(OS_ARCH))
 ifneq (Android,$(OS_TARGET))
--- a/toolkit/toolkit-makefiles.sh
+++ b/toolkit/toolkit-makefiles.sh
@@ -729,16 +729,20 @@ MAKEFILES_extensions="
   extensions/pref/autoconfig/public/Makefile
   extensions/pref/autoconfig/src/Makefile
 "
 
 MAKEFILES_startupcache="
   startupcache/Makefile
 "
 
+MAKEFILES_hal="
+  hal/Makefile
+"
+
 add_makefiles "
   $MAKEFILES_db
   $MAKEFILES_dom
   $MAKEFILES_editor
   $MAKEFILES_xmlparser
   $MAKEFILES_gfx
   $MAKEFILES_htmlparser
   $MAKEFILES_intl
@@ -770,16 +774,17 @@ add_makefiles "
   $MAKEFILES_xpfe
   $MAKEFILES_embedding
   $MAKEFILES_xulapp
   $MAKEFILES_libpr0n
   $MAKEFILES_accessible
   $MAKEFILES_libmar
   $MAKEFILES_extensions
   $MAKEFILES_startupcache
+  $MAKEFILES_hal
 "
 
 #
 # Conditional makefiles
 #
 
 if [ "$ENABLE_TESTS" ]; then
   add_makefiles "
--- a/toolkit/toolkit-tiers.mk
+++ b/toolkit/toolkit-tiers.mk
@@ -89,16 +89,17 @@ tier_platform_dirs	+= gfx/qcms
 
 #
 # "gecko" - core components
 #
 
 tier_platform_dirs += ipc js/ipc js/jetpack
 
 tier_platform_dirs += \
+		hal \
 		js/src/xpconnect \
 		intl/chardet \
 		$(NULL)
 
 ifdef MOZ_ENABLE_GTK2
 ifdef MOZ_X11
 tier_platform_dirs     += widget/src/gtkxtbin
 endif
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -55,16 +55,17 @@
 #include <QtGui/QInputContext>
 #ifdef MOZ_ENABLE_MEEGOTOUCH
 #include <MComponentData>
 #include <MozMeegoAppService.h>
 #endif // MOZ_ENABLE_MEEGOTOUCH
 #endif // MOZ_WIDGET_QT
 
 #include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/ContentChild.h"
 
 #include "nsAppRunner.h"
 #include "nsUpdateDriver.h"
 
 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
 #include "EventTracer.h"
 #endif
 
@@ -248,16 +249,17 @@ static char **gQtOnlyArgv;
 #ifdef MOZ_X11
 #include <gdk/gdkx.h>
 #endif /* MOZ_X11 */
 #include "nsGTKToolkit.h"
 #endif
 #include "BinaryPath.h"
 
 using mozilla::dom::ContentParent;
+using mozilla::dom::ContentChild;
 
 // Save literal putenv string to environment variable.
 static void
 SaveToEnv(const char *putenv)
 {
   char *expr = strdup(putenv);
   if (expr)
     PR_SetEnv(expr);
@@ -602,17 +604,18 @@ NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
   NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
 #ifdef XP_WIN
   NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
 #endif
 #ifdef MOZ_CRASHREPORTER
   NS_INTERFACE_MAP_ENTRY(nsICrashReporter)
 #endif
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData || 
+                                     XRE_GetProcessType() == GeckoProcessType_Content)
 NS_INTERFACE_MAP_END
 
 NS_IMETHODIMP_(nsrefcnt)
 nsXULAppInfo::AddRef()
 {
   return 1;
 }
 
@@ -620,56 +623,78 @@ NS_IMETHODIMP_(nsrefcnt)
 nsXULAppInfo::Release()
 {
   return 1;
 }
 
 NS_IMETHODIMP
 nsXULAppInfo::GetVendor(nsACString& aResult)
 {
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    NS_WARNING("Attempt to get unavailable information in content process.");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
   aResult.Assign(gAppData->vendor);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULAppInfo::GetName(nsACString& aResult)
 {
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    NS_WARNING("Attempt to get unavailable information in content process.");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
   aResult.Assign(gAppData->name);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULAppInfo::GetID(nsACString& aResult)
 {
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    NS_WARNING("Attempt to get unavailable information in content process.");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
   aResult.Assign(gAppData->ID);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULAppInfo::GetVersion(nsACString& aResult)
 {
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    ContentChild* cc = ContentChild::GetSingleton();
+    aResult = cc->GetAppInfo().version;
+    return NS_OK;
+  }
   aResult.Assign(gAppData->version);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULAppInfo::GetPlatformVersion(nsACString& aResult)
 {
   aResult.Assign(gToolkitVersion);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULAppInfo::GetAppBuildID(nsACString& aResult)
 {
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    ContentChild* cc = ContentChild::GetSingleton();
+    aResult = cc->GetAppInfo().buildID;
+    return NS_OK;
+  }
   aResult.Assign(gAppData->buildID);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULAppInfo::GetPlatformBuildID(nsACString& aResult)
 {
--- a/tools/jprof/Makefile.in
+++ b/tools/jprof/Makefile.in
@@ -51,16 +51,17 @@ CPPSRCS = \
 	coff.cpp   \
 	elf.cpp	   \
 	leaky.cpp  \
 	strset.cpp \
 	intcnt.cpp \
 	$(NULL)
 
 OS_LIBS = \
+	-ldl \
 	-lbfd \
 	-liberty \
 	$(NULL)
 
 HELPER_SCRIPTS	= jprofsig
 HELPER_SCRIPTS	:= $(addprefix $(srcdir)/, $(HELPER_SCRIPTS))
 
 include $(topsrcdir)/config/rules.mk
--- a/xpcom/glue/nsTArray.h
+++ b/xpcom/glue/nsTArray.h
@@ -1279,31 +1279,46 @@ private:
   };
 };
 
 template<class E, PRUint32 N, class Alloc=nsTArrayDefaultAllocator>
 class nsAutoTArray : public nsAutoArrayBase<nsTArray<E, Alloc>, N>
 {
 public:
   nsAutoTArray() {}
+
+  template<typename Allocator>
+  nsAutoTArray(const nsTArray<E, Allocator>& other) {
+    AppendElements(other);
+  }
 };
 
 template<class E, PRUint32 N>
 class AutoFallibleTArray : public nsAutoArrayBase<FallibleTArray<E>, N>
 {
 public:
   AutoFallibleTArray() {}
+
+  template<typename Allocator>
+  AutoFallibleTArray(const nsTArray<E, Allocator>& other) {
+    AppendElements(other);
+  }
 };
 
 #if defined(MOZALLOC_HAVE_XMALLOC)
 template<class E, PRUint32 N>
 class AutoInfallibleTArray : public nsAutoArrayBase<InfallibleTArray<E>, N>
 {
 public:
   AutoInfallibleTArray() {}
+
+  template<typename Allocator>
+  AutoInfallibleTArray(const nsTArray<E, Allocator>& other) {
+    AppendElements(other);
+  }
 };
 #endif
 
 // specializations for N = 0. this makes the inheritance model easier for
 // templated users of nsAutoTArray.
 template<class E>
 class nsAutoTArray<E, 0, nsTArrayDefaultAllocator> :
   public nsAutoArrayBase< nsTArray<E, nsTArrayDefaultAllocator>, 0>