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 78182 f107192c7d5936c81814f00967f580aaca99ed32
parent 78162 8c82de08425d6fc7a9b235311d07ed4f6af0717e (current diff)
parent 78181 7e1f77774d9eee2b3d1b6b6baaa0c4656bfa5b0d (diff)
child 78187 62ea504b378d32e3b10cb6358a5ae869285eb7e5
push id21275
push userbmo@edmorley.co.uk
push dateThu, 06 Oct 2011 10:15:46 +0000
treeherdermozilla-central@f107192c7d59 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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>