Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 10 Dec 2012 13:56:39 -0500
changeset 124605 00e26dece6ea2c3893a07f0202f5128aaa5ca425
parent 124544 c6970a82a686c0c9899a117a09a904fbc851e9c6 (current diff)
parent 124604 d6dd73183bce274301d260a60f73f86078faeb8c (diff)
child 124606 99c2b5cf341c673bd27b036cc6e13de6b533cc5f
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone20.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 the last PGO-green inbound changeset to m-c.
dom/apps/src/PermissionsInstaller.jsm
--- a/accessible/src/base/AccCollector.h
+++ b/accessible/src/base/AccCollector.h
@@ -69,17 +69,17 @@ private:
 
 /**
  * Collect embedded objects. Provide quick access to accessible by index and
  * vice versa.
  */
 class EmbeddedObjCollector : public AccCollector
 {
 public:
-  virtual ~EmbeddedObjCollector() { };
+  virtual ~EmbeddedObjCollector() { }
 
 public:
   virtual int32_t GetIndexAt(Accessible* aAccessible);
 
 protected:
   // Make sure it's used by Accessible class only.
   EmbeddedObjCollector(Accessible* aRoot) :
     AccCollector(aRoot, filters::GetEmbeddedObject) { }
--- a/accessible/src/base/AccEvent.h
+++ b/accessible/src/base/AccEvent.h
@@ -208,17 +208,17 @@ public:
                    nsINode* aTargetNode) :
     AccEvent(aEventType, aTarget, eAutoDetect, eCoalesceMutationTextChange)
   {
     // Don't coalesce these since they are coalesced by reorder event. Coalesce
     // contained text change events.
     mNode = aTargetNode;
     mParent = mAccessible->Parent();
   }
-  virtual ~AccMutationEvent() { };
+  virtual ~AccMutationEvent() { }
 
   // Event
   static const EventGroup kEventGroup = eMutationEvent;
   virtual unsigned int GetEventGroups() const
   {
     return AccEvent::GetEventGroups() | (1U << eMutationEvent);
   }
 
@@ -286,17 +286,17 @@ public:
  * Class for reorder accessible event. Takes care about
  */
 class AccReorderEvent : public AccEvent
 {
 public:
   AccReorderEvent(Accessible* aTarget) :
     AccEvent(::nsIAccessibleEvent::EVENT_REORDER, aTarget,
              eAutoDetect, eCoalesceReorder) { }
-  virtual ~AccReorderEvent() { };
+  virtual ~AccReorderEvent() { }
 
   // Event
   static const EventGroup kEventGroup = eReorderEvent;
   virtual unsigned int GetEventGroups() const
   {
     return AccEvent::GetEventGroups() | (1U << eReorderEvent);
   }
 
--- a/accessible/src/base/NotificationController.h
+++ b/accessible/src/base/NotificationController.h
@@ -23,17 +23,17 @@ class Accessible;
 class DocAccessible;
 
 /**
  * Notification interface.
  */
 class Notification
 {
 public:
-  virtual ~Notification() { };
+  virtual ~Notification() { }
 
   NS_INLINE_DECL_REFCOUNTING(Notification)
 
   /**
    * Process notification.
    */
   virtual void Process() = 0;
 
--- a/accessible/src/base/StyleInfo.h
+++ b/accessible/src/base/StyleInfo.h
@@ -12,17 +12,17 @@
 
 namespace mozilla {
 namespace a11y {
 
 class StyleInfo
 {
 public:
   StyleInfo(dom::Element* aElement, nsIPresShell* aPresShell);
-  ~StyleInfo() { };
+  ~StyleInfo() { }
 
   void Display(nsAString& aValue);
   void TextAlign(nsAString& aValue);
   void TextIndent(nsAString& aValue);
   void MarginLeft(nsAString& aValue) { Margin(css::eSideLeft, aValue); }
   void MarginRight(nsAString& aValue) { Margin(css::eSideRight, aValue); }
   void MarginTop(nsAString& aValue) { Margin(css::eSideTop, aValue); }
   void MarginBottom(nsAString& aValue) { Margin(css::eSideBottom, aValue); }
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -299,18 +299,18 @@ public:
 
 
 /**
  * nsIDOMDOMStringList implementation.
  */
 class nsAccessibleDOMStringList : public nsIDOMDOMStringList
 {
 public:
-  nsAccessibleDOMStringList() {};
-  virtual ~nsAccessibleDOMStringList() {};
+  nsAccessibleDOMStringList() {}
+  virtual ~nsAccessibleDOMStringList() {}
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMDOMSTRINGLIST
 
   bool Add(const nsAString& aName) {
     return mNames.AppendElement(aName) != nullptr;
   }
 
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -945,17 +945,17 @@ public:
   static const uint32_t kShift = 1;
   static const uint32_t kControl = 2;
   static const uint32_t kAlt = 4;
   static const uint32_t kMeta = 8;
   static const uint32_t kOS = 16;
 
   KeyBinding() : mKey(0), mModifierMask(0) {}
   KeyBinding(uint32_t aKey, uint32_t aModifierMask) :
-    mKey(aKey), mModifierMask(aModifierMask) {};
+    mKey(aKey), mModifierMask(aModifierMask) {}
 
   inline bool IsEmpty() const { return !mKey; }
   inline uint32_t Key() const { return mKey; }
   inline uint32_t ModifierMask() const { return mModifierMask; }
 
   enum Format {
     ePlatformFormat,
     eAtkFormat
--- a/accessible/src/html/HTMLElementAccessibles.h
+++ b/accessible/src/html/HTMLElementAccessibles.h
@@ -15,30 +15,30 @@ namespace a11y {
 /**
  * Used for HTML hr element.
  */
 class HTMLHRAccessible : public LeafAccessible
 {
 public:
 
   HTMLHRAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-    LeafAccessible(aContent, aDoc) {};
+    LeafAccessible(aContent, aDoc) {}
 
   // Accessible
   virtual a11y::role NativeRole();
 };
 
 /**
  * Used for HTML br element.
  */
 class HTMLBRAccessible : public LeafAccessible
 {
 public:
   HTMLBRAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-    LeafAccessible(aContent, aDoc) {};
+    LeafAccessible(aContent, aDoc) {}
 
   // Accessible
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
 
 protected:
   // Accessible
   virtual ENameValueFlag NativeName(nsString& aName) MOZ_OVERRIDE;
@@ -47,17 +47,17 @@ protected:
 /**
  * Used for HTML label element.
  */
 class HTMLLabelAccessible : public HyperTextAccessibleWrap
 {
 public:
 
   HTMLLabelAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-    HyperTextAccessibleWrap(aContent, aDoc) {};
+    HyperTextAccessibleWrap(aContent, aDoc) {}
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // Accessible
   virtual a11y::role NativeRole();
 
 protected:
   virtual ENameValueFlag NativeName(nsString& aName) MOZ_OVERRIDE;
@@ -66,17 +66,17 @@ protected:
 /**
  * Used for HTML output element.
  */
 class HTMLOutputAccessible : public HyperTextAccessibleWrap
 {
 public:
 
   HTMLOutputAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-    HyperTextAccessibleWrap(aContent, aDoc) {};
+    HyperTextAccessibleWrap(aContent, aDoc) {}
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // Accessible
   virtual a11y::role NativeRole();
   virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual Relation RelationByType(uint32_t aType);
 };
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -118,17 +118,16 @@ endif
                  browser_bug537474.js \
                  browser_bug550565.js \
                  browser_bug553455.js \
                  browser_bug555224.js \
                  browser_bug555767.js \
                  browser_bug556061.js \
                  browser_bug559991.js \
                  browser_bug561623.js \
-                 browser_bug561636.js \
                  browser_bug562649.js \
                  browser_bug563588.js \
                  browser_bug565575.js \
                  browser_bug567306.js \
                  browser_zbug569342.js \
                  browser_bug575561.js \
                  browser_bug575830.js \
                  browser_bug577121.js \
@@ -309,20 +308,25 @@ endif
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
 else
 _BROWSER_FILES += \
 		browser_bug565667.js \
 		$(NULL)
+# TODO: Activate after carbon test plugin lands, bug 628651
+# 		browser_maconly_carbon_mismatch_plugin.js
+endif
 
-# TODO: Activate after carbon test plugin lands, bug 628651
-# 		browser_maconly_carbon_mismatch_plugin.js \
-
+# bug 766546, disable browser_bug561636.js on Windows
+ifneq ($(OS_ARCH),WINNT)
+_BROWSER_FILES += \
+                 browser_bug561636.js \
+                 $(NULL)
 endif
 
 ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
 _BROWSER_FILES += \
                 browser_bug763468_perwindowpb.js \
                 browser_bug767836_perwindowpb.js \
                 browser_bug816527.js \
                 browser_private_browsing_window.js \
--- a/browser/devtools/commandline/test/Makefile.in
+++ b/browser/devtools/commandline/test/Makefile.in
@@ -7,28 +7,31 @@ DEPTH     = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_BROWSER_FILES = \
+  browser_dbg_cmd_break.html \
   browser_dbg_cmd_break.js \
+  browser_dbg_cmd.html \
   browser_dbg_cmd.js \
   browser_cmd_addon.js \
-  browser_cmd_calllog.js \
-  browser_cmd_calllog_chrome.js \
   browser_cmd_commands.js \
   browser_cmd_cookie.js \
   browser_cmd_integrate.js \
   browser_cmd_jsb.js \
+  browser_cmd_jsb_script.jsi \
+  browser_cmd_pagemod_export.html \
   browser_cmd_pagemod_export.js \
   browser_cmd_pref.js \
   browser_cmd_restart.js \
+  browser_cmd_screenshot.html \
   browser_cmd_settings.js \
   browser_gcli_canon.js \
   browser_gcli_cli.js \
   browser_gcli_completion.js \
   browser_gcli_exec.js \
   browser_gcli_focus.js \
   browser_gcli_history.js \
   browser_gcli_incomplete.js \
@@ -57,17 +60,19 @@ MOCHITEST_BROWSER_FILES += \
  browser_cmd_screenshot_perwindowpb.js \
  $(NULL)
 else
 MOCHITEST_BROWSER_FILES += \
  browser_cmd_screenshot.js \
  $(NULL)
 endif
 
+ifneq ($(OS_ARCH),WINNT)
 MOCHITEST_BROWSER_FILES += \
-  browser_dbg_cmd_break.html \
-  browser_dbg_cmd.html \
-  browser_cmd_screenshot.html \
-  browser_cmd_pagemod_export.html \
-  browser_cmd_jsb_script.jsi \
+  browser_cmd_calllog.js \
+  browser_cmd_calllog_chrome.js \
   $(NULL)
+else
+$(filter disabled-temporarily--bug-817304, browser_cmd_calllog.js)
+$(filter disabled-temporarily--bug-819017, browser_cmd_calllog_chrome.js)
+endif
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/devtools/webconsole/test/Makefile.in
+++ b/browser/devtools/webconsole/test/Makefile.in
@@ -99,17 +99,17 @@ MOCHITEST_BROWSER_FILES = \
 	browser_webconsole_bug_659907_console_dir.js \
 	browser_webconsole_bug_664131_console_group.js \
 	browser_webconsole_bug_704295.js \
 	browser_webconsole_bug_658368_time_methods.js \
 	browser_webconsole_bug_764572_output_open_url.js \
 	browser_webconsole_bug_622303_persistent_filters.js \
 	browser_webconsole_bug_770099_bad_policyuri.js \
 	browser_webconsole_bug_770099_violation.js \
-	browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js \
+	$(filter disabled-temporarily--bug-808264, browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js) \
 	browser_cached_messages.js \
 	browser_bug664688_sandbox_update_after_navigation.js \
 	browser_result_format_as_string.js \
 	browser_webconsole_bug_737873_mixedcontent.js \
 	browser_output_breaks_after_console_dir_uninspectable.js \
 	browser_console_log_inspectable_object.js \
 	browser_bug_638949_copy_link_location.js \
 	browser_output_longstring_expand.js \
--- a/build/unix/elfhack/elf.cpp
+++ b/build/unix/elfhack/elf.cpp
@@ -324,24 +324,42 @@ ElfSection *Elf::getSectionAt(unsigned i
         ElfSection *section = getSection(i);
         if ((section != NULL) && (section->getFlags() & SHF_ALLOC) && !(section->getFlags() & SHF_TLS) &&
             (offset >= section->getAddr()) && (offset < section->getAddr() + section->getSize()))
             return section;
     }
     return NULL;
 }
 
-ElfSegment *Elf::getSegmentByType(unsigned int type)
+ElfSegment *Elf::getSegmentByType(unsigned int type, ElfSegment *last)
 {
-    for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
+    std::vector<ElfSegment *>::iterator seg;
+    if (last) {
+        seg = std::find(segments.begin(), segments.end(), last);
+        ++seg;
+    } else
+        seg = segments.begin();
+    for (; seg != segments.end(); seg++)
         if ((*seg)->getType() == type)
             return *seg;
     return NULL;
 }
 
+void Elf::removeSegment(ElfSegment *segment)
+{
+    if (!segment)
+        return;
+    std::vector<ElfSegment *>::iterator seg;
+    seg = std::find(segments.begin(), segments.end(), segment);
+    if (seg == segments.end())
+        return;
+    segment->clear();
+    segments.erase(seg);
+}
+
 ElfDynamic_Section *Elf::getDynSection()
 {
     for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
         if (((*seg)->getType() == PT_DYNAMIC) && ((*seg)->getFirstSection() != NULL) &&
             (*seg)->getFirstSection()->getType() == SHT_DYNAMIC)
             return (ElfDynamic_Section *)(*seg)->getFirstSection();
 
     return NULL;
@@ -354,30 +372,25 @@ void Elf::normalize()
     for (ElfSection *section = ehdr; section != NULL; section = section->getNext()) {
         if (section->getIndex() == 0)
             continue;
         else
             ehdr->e_shnum = section->getIndex() + 1;
         section->getShdr().sh_name = eh_shstrndx->getStrIndex(section->getName());
     }
     ehdr->markDirty();
-    // Adjust PT_LOAD segments
+    // Check segments consistency
     int i = 0;
     for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++, i++) {
-        if ((*seg)->getType() == PT_LOAD) {
-            std::list<ElfSection *>::iterator it = (*seg)->begin();
-            for (ElfSection *last = *(it++); it != (*seg)->end(); last = *(it++)) {
-               if (((*it)->getType() != SHT_NOBITS) &&
-                   ((*it)->getAddr() - last->getAddr()) != ((*it)->getOffset() - last->getOffset())) {
-                   std::vector<ElfSegment *>::iterator next = seg;
-                   segments.insert(++next, (*seg)->splitBefore(*it));
-                   seg = segments.begin() + i;
-                   break;
-               }
-           }
+        std::list<ElfSection *>::iterator it = (*seg)->begin();
+        for (ElfSection *last = *(it++); it != (*seg)->end(); last = *(it++)) {
+            if (((*it)->getType() != SHT_NOBITS) &&
+                ((*it)->getAddr() - last->getAddr()) != ((*it)->getOffset() - last->getOffset())) {
+                    throw std::runtime_error("Segments inconsistency");
+            }
         }
     }
     // fixup ehdr before writing
     if (ehdr->e_phnum != segments.size()) {
         ehdr->e_phnum = segments.size();
         phdr_section->getShdr().sh_size = segments.size() * Elf_Phdr::size(ehdr->e_ident[EI_CLASS]);
         phdr_section->getNext()->markDirty();
     }
@@ -476,16 +489,25 @@ unsigned int ElfSection::getOffset()
 {
     if (shdr.sh_offset != (Elf32_Word)-1)
         return shdr.sh_offset;
 
     if (previous == NULL)
         return (shdr.sh_offset = 0);
 
     unsigned int offset = previous->getOffset();
+
+    ElfSegment *ptload = getSegmentByType(PT_LOAD);
+    ElfSegment *prev_ptload = previous->getSegmentByType(PT_LOAD);
+
+    if (ptload && (ptload == prev_ptload)) {
+        offset += getAddr() - previous->getAddr();
+        return (shdr.sh_offset = offset);
+    }
+
     if (previous->getType() != SHT_NOBITS)
         offset += previous->getSize();
 
     Elf32_Word align = 0x1000;
     for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
         align = std::max(align, (*seg)->getAlign());
 
     Elf32_Word mask = align - 1;
@@ -550,16 +572,22 @@ void ElfSegment::addSection(ElfSection *
     std::list<ElfSection *>::iterator i;
     for (i = sections.begin(); i != sections.end(); ++i)
         if ((*i)->getAddr() > section->getAddr())
             break;
     sections.insert(i, section);
     section->addToSegment(this);
 }
 
+void ElfSegment::removeSection(ElfSection *section)
+{
+    sections.remove(section);
+    section->removeFromSegment(this);
+}
+
 unsigned int ElfSegment::getFileSize()
 {
     if (type == PT_GNU_RELRO)
         return filesz;
 
     if (sections.empty())
         return 0;
     // Search the last section that is not SHT_NOBITS
@@ -600,41 +628,21 @@ unsigned int ElfSegment::getAddr()
 {
     if ((type == PT_GNU_RELRO) && !sections.empty() &&
         (sections.front()->getAddr() != vaddr))
         throw std::runtime_error("PT_GNU_RELRO segment doesn't start on a section start");
 
     return sections.empty() ? 0 : sections.front()->getAddr();
 }
 
-ElfSegment *ElfSegment::splitBefore(ElfSection *section)
+void ElfSegment::clear()
 {
-    std::list<ElfSection *>::iterator i, rm;
-    for (i = sections.begin(); (*i != section) && (i != sections.end()); ++i);
-    if (i == sections.end())
-        return NULL;
-
-    // Probably very wrong.
-    Elf_Phdr phdr;
-    phdr.p_type = type;
-    phdr.p_vaddr = 0;
-    phdr.p_paddr = phdr.p_vaddr + v_p_diff;
-    phdr.p_flags = flags;
-    phdr.p_align = getAlign();
-    phdr.p_filesz = (unsigned int)-1;
-    phdr.p_memsz = (unsigned int)-1;
-    ElfSegment *segment = new ElfSegment(&phdr);
-
-    for (rm = i; i != sections.end(); ++i) {
+    for (std::list<ElfSection *>::iterator i = sections.begin(); i != sections.end(); ++i)
         (*i)->removeFromSegment(this);
-        segment->addSection(*i);
-    }
-    sections.erase(rm, sections.end());
-
-    return segment;
+    sections.clear();
 }
 
 ElfValue *ElfDynamic_Section::getValueForType(unsigned int tag)
 {
     for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
         if (dyns[i].tag == tag)
             return dyns[i].value;
 
--- a/build/unix/elfhack/elfhack.cpp
+++ b/build/unix/elfhack/elfhack.cpp
@@ -371,16 +371,47 @@ void set_relative_reloc(Elf_Rel *rel, El
 
 void set_relative_reloc(Elf_Rela *rel, Elf *elf, unsigned int value) {
     // ld puts the value of relocated relocations both in the addend and
     // at r_offset. For consistency, keep it that way.
     set_relative_reloc((Elf_Rel *)rel, elf, value);
     rel->r_addend = value;
 }
 
+void maybe_split_segment(Elf *elf, ElfSegment *segment)
+{
+    std::list<ElfSection *>::iterator it = segment->begin();
+    for (ElfSection *last = *(it++); it != segment->end(); last = *(it++)) {
+        // When two consecutive non-SHT_NOBITS sections are apart by more
+        // than the alignment of the section, the second can be moved closer
+        // to the first, but this requires the segment to be split.
+        if (((*it)->getType() != SHT_NOBITS) && (last->getType() != SHT_NOBITS) &&
+            ((*it)->getOffset() - last->getOffset() - last->getSize() > segment->getAlign())) {
+            // Probably very wrong.
+            Elf_Phdr phdr;
+            phdr.p_type = PT_LOAD;
+            phdr.p_vaddr = 0;
+            phdr.p_paddr = phdr.p_vaddr + segment->getVPDiff();
+            phdr.p_flags = segment->getFlags();
+            phdr.p_align = segment->getAlign();
+            phdr.p_filesz = (unsigned int)-1;
+            phdr.p_memsz = (unsigned int)-1;
+            ElfSegment *newSegment = new ElfSegment(&phdr);
+            elf->insertSegmentAfter(segment, newSegment);
+            for (; it != segment->end(); ++it) {
+                newSegment->addSection(*it);
+            }
+            for (it = newSegment->begin(); it != newSegment->end(); it++) {
+                segment->removeSection(*it);
+            }
+            break;
+        }
+    }
+}
+
 template <typename Rel_Type>
 int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type2, bool force)
 {
     ElfDynamic_Section *dyn = elf->getDynSection();
     if (dyn ==NULL) {
         fprintf(stderr, "Couldn't find SHT_DYNAMIC section\n");
         return -1;
     }
@@ -518,26 +549,33 @@ int do_relocation_section(Elf *elf, unsi
             ElfSymtab_Section *symtab = (ElfSymtab_Section *)section->getLink();
             original_init = symtab->syms[ELF32_R_SYM(rel->r_info)].value.getValue() + addend;
         } else {
             fprintf(stderr, "Unsupported relocation type for DT_INIT_ARRAY's first entry. Skipping\n");
             return -1;
         }
     }
 
+    section->rels.assign(new_rels.begin(), new_rels.end());
+    section->shrink(new_rels.size() * section->getEntSize());
+
     ElfRelHackCode_Section *relhackcode = new ElfRelHackCode_Section(relhackcode_section, *elf, original_init);
     relhackcode->insertBefore(section);
     relhack->insertAfter(relhackcode);
-
-    section->rels.assign(new_rels.begin(), new_rels.end());
-    section->shrink(new_rels.size() * section->getEntSize());
     if (section->getOffset() + section->getSize() >= old_end) {
         fprintf(stderr, "No gain. Skipping\n");
         return -1;
     }
+
+    // Adjust PT_LOAD segments
+    for (ElfSegment *segment = elf->getSegmentByType(PT_LOAD); segment;
+         segment = elf->getSegmentByType(PT_LOAD, segment)) {
+        maybe_split_segment(elf, segment);
+    }
+
     // Ensure Elf sections will be at their final location.
     elf->normalize();
     ElfLocation *init = new ElfLocation(relhackcode, relhackcode->getEntryPoint());
     if (init_array) {
         // Adjust the first DT_INIT_ARRAY entry to point at the injected code
         // by transforming its relocation into a relative one pointing to the
         // address of the injected code.
         Rel_Type *rel = &section->rels[init_array_reloc - 1];
@@ -559,73 +597,129 @@ static inline int backup_file(const char
     std::string fname(name);
     fname += ".bak";
     return rename(name, fname.c_str());
 }
 
 void do_file(const char *name, bool backup = false, bool force = false)
 {
     std::ifstream file(name, std::ios::in|std::ios::binary);
-    Elf *elf = new Elf(file);
-    unsigned int size = elf->getSize();
+    Elf elf(file);
+    unsigned int size = elf.getSize();
     fprintf(stderr, "%s: ", name);
-    if (elf->getType() != ET_DYN) {
+    if (elf.getType() != ET_DYN) {
         fprintf(stderr, "Not a shared object. Skipping\n");
-        delete elf;
         return;
     }
 
-    for (ElfSection *section = elf->getSection(1); section != NULL;
+    for (ElfSection *section = elf.getSection(1); section != NULL;
          section = section->getNext()) {
         if (section->getName() &&
             (strncmp(section->getName(), ".elfhack.", 9) == 0)) {
             fprintf(stderr, "Already elfhacked. Skipping\n");
-            delete elf;
             return;
         }
     }
 
     int exit = -1;
-    switch (elf->getMachine()) {
+    switch (elf.getMachine()) {
     case EM_386:
-        exit = do_relocation_section<Elf_Rel>(elf, R_386_RELATIVE, R_386_32, force);
+        exit = do_relocation_section<Elf_Rel>(&elf, R_386_RELATIVE, R_386_32, force);
         break;
     case EM_X86_64:
-        exit = do_relocation_section<Elf_Rela>(elf, R_X86_64_RELATIVE, R_X86_64_64, force);
+        exit = do_relocation_section<Elf_Rela>(&elf, R_X86_64_RELATIVE, R_X86_64_64, force);
         break;
     case EM_ARM:
-        exit = do_relocation_section<Elf_Rel>(elf, R_ARM_RELATIVE, R_ARM_ABS32, force);
+        exit = do_relocation_section<Elf_Rel>(&elf, R_ARM_RELATIVE, R_ARM_ABS32, force);
         break;
     }
     if (exit == 0) {
-        if (!force && (elf->getSize() >= size)) {
+        if (!force && (elf.getSize() >= size)) {
             fprintf(stderr, "No gain. Skipping\n");
         } else if (backup && backup_file(name) != 0) {
             fprintf(stderr, "Couln't create backup file\n");
         } else {
             std::ofstream ofile(name, std::ios::out|std::ios::binary|std::ios::trunc);
-            elf->write(ofile);
-            fprintf(stderr, "Reduced by %d bytes\n", size - elf->getSize());
+            elf.write(ofile);
+            fprintf(stderr, "Reduced by %d bytes\n", size - elf.getSize());
         }
     }
-    delete elf;
+}
+
+void undo_file(const char *name, bool backup = false)
+{
+    std::ifstream file(name, std::ios::in|std::ios::binary);
+    Elf elf(file);
+    unsigned int size = elf.getSize();
+    fprintf(stderr, "%s: ", name);
+    if (elf.getType() != ET_DYN) {
+        fprintf(stderr, "Not a shared object. Skipping\n");
+        return;
+    }
+
+    ElfSection *data = NULL, *text = NULL;
+    for (ElfSection *section = elf.getSection(1); section != NULL;
+         section = section->getNext()) {
+        if (section->getName() &&
+            (strcmp(section->getName(), elfhack_data) == 0))
+            data = section;
+        if (section->getName() &&
+            (strcmp(section->getName(), elfhack_text) == 0))
+            text = section;
+    }
+
+    if (!data || !text) {
+        fprintf(stderr, "Not elfhacked. Skipping\n");
+        return;
+    }
+    if (data != text->getNext()) {
+        fprintf(stderr, elfhack_data " section not following " elfhack_text ". Skipping\n");
+        return;
+    }
+
+    ElfSegment *first = elf.getSegmentByType(PT_LOAD);
+    ElfSegment *second = elf.getSegmentByType(PT_LOAD, first);
+    if (second->getFlags() != first->getFlags()) {
+        fprintf(stderr, "First two PT_LOAD segments don't have the same flags. Skipping\n");
+        return;
+    }
+    // Move sections from the second PT_LOAD to the first, and remove the
+    // second PT_LOAD segment.
+    for (std::list<ElfSection *>::iterator section = second->begin();
+         section != second->end(); ++section)
+        first->addSection(*section);
+
+    elf.removeSegment(second);
+
+    if (backup && backup_file(name) != 0) {
+        fprintf(stderr, "Couln't create backup file\n");
+    } else {
+        std::ofstream ofile(name, std::ios::out|std::ios::binary|std::ios::trunc);
+        elf.write(ofile);
+        fprintf(stderr, "Grown by %d bytes\n", elf.getSize() - size);
+    }
 }
 
 int main(int argc, char *argv[])
 {
     int arg;
     bool backup = false;
     bool force = false;
+    bool revert = false;
     char *lastSlash = rindex(argv[0], '/');
     if (lastSlash != NULL)
         rundir = strndup(argv[0], lastSlash - argv[0]);
     for (arg = 1; arg < argc; arg++) {
         if (strcmp(argv[arg], "-f") == 0)
             force = true;
         else if (strcmp(argv[arg], "-b") == 0)
             backup = true;
+        else if (strcmp(argv[arg], "-r") == 0)
+            revert = true;
+        else if (revert)
+            undo_file(argv[arg], backup);
         else
             do_file(argv[arg], backup, force);
     }
 
     free(rundir);
     return 0;
 }
--- a/build/unix/elfhack/elfxx.h
+++ b/build/unix/elfhack/elfxx.h
@@ -265,28 +265,36 @@ public:
     Elf(std::ifstream &file);
     ~Elf();
 
     /* index == -1 is treated as index == ehdr.e_shstrndx */
     ElfSection *getSection(int index);
 
     ElfSection *getSectionAt(unsigned int offset);
 
-    ElfSegment *getSegmentByType(unsigned int type);
+    ElfSegment *getSegmentByType(unsigned int type, ElfSegment *last = NULL);
 
     ElfDynamic_Section *getDynSection();
 
     void normalize();
     void write(std::ofstream &file);
 
     char getClass();
     char getData();
     char getType();
     char getMachine();
     unsigned int getSize();
+
+    void insertSegmentAfter(ElfSegment *previous, ElfSegment *segment) {
+        std::vector<ElfSegment *>::iterator prev = std::find(segments.begin(), segments.end(), previous);
+        segments.insert(prev + 1, segment);
+    }
+
+    void removeSegment(ElfSegment *segment);
+
 private:
     Elf_Ehdr *ehdr;
     ElfLocation eh_entry;
     ElfStrtab_Section *eh_shstrndx;
     ElfSection **sections;
     std::vector<ElfSegment *> segments;
     ElfSection *shdr_section, *phdr_section;
     /* Values used only during initialization */
@@ -314,21 +322,18 @@ public:
     unsigned int getSize() { return shdr.sh_size; }
     unsigned int getAddrAlign() { return shdr.sh_addralign; }
     unsigned int getEntSize() { return shdr.sh_entsize; }
     const char *getData() { return data; }
     ElfSection *getLink() { return link; }
     SectionInfo getInfo() { return info; }
 
     void shrink(unsigned int newsize) {
-        if (newsize < shdr.sh_size) {
+        if (newsize < shdr.sh_size)
             shdr.sh_size = newsize;
-            if (next)
-                next->markDirty();
-        }
     }
 
     unsigned int getOffset();
     int getIndex();
     Elf_Shdr &getShdr();
 
     ElfSection *getNext() { return next; }
     ElfSection *getPrevious() { return previous; }
@@ -340,17 +345,17 @@ public:
                 (getType() == SHT_HASH) ||
                 (getType() == SHT_NOTE) ||
                 (getType() == SHT_REL) ||
                 (getType() == SHT_DYNSYM) ||
                 (getType() == SHT_GNU_HASH) ||
                 (getType() == SHT_GNU_verdef) ||
                 (getType() == SHT_GNU_verneed) ||
                 (getType() == SHT_GNU_versym) ||
-                isInSegmentType(PT_INTERP)) &&
+                getSegmentByType(PT_INTERP)) &&
                 (getFlags() & SHF_ALLOC);
     }
 
     void insertAfter(ElfSection *section, bool dirty = true) {
         if (previous != NULL)
             previous->next = next;
         if (next != NULL)
             next->previous = previous;
@@ -359,16 +364,17 @@ public:
             next = section->next;
             section->next = this;
         } else
             next = NULL;
         if (next != NULL)
             next->previous = this;
         if (dirty)
             markDirty();
+        insertInSegments(section->segments);
     }
 
     void insertBefore(ElfSection *section, bool dirty = true) {
         if (previous != NULL)
             previous->next = next;
         if (next != NULL)
             next->previous = previous;
         next = section;
@@ -376,16 +382,17 @@ public:
             previous = section->previous;
             section->previous = this;
         } else
             previous = NULL;
         if (previous != NULL)
             previous->next = this;
         if (dirty)
             markDirty();
+        insertInSegments(section->segments);
     }
 
     void markDirty() {
         if (link != NULL)
             shdr.sh_link = -1;
         if (info.index)
             shdr.sh_info = -1;
         shdr.sh_offset = -1;
@@ -410,17 +417,20 @@ private:
         segments.push_back(segment);
     }
 
     void removeFromSegment(ElfSegment *segment) {
         std::vector<ElfSegment *>::iterator i = std::find(segments.begin(), segments.end(), segment);
         segments.erase(i, i + 1);
     }
 
-    bool isInSegmentType(unsigned int type);
+    ElfSegment *getSegmentByType(unsigned int type);
+
+    void insertInSegments(std::vector<ElfSegment *> &segs);
+
 protected:
     Elf_Shdr shdr;
     char *data;
     const char *name;
 private:
     ElfSection *link;
     SectionInfo info;
     ElfSection *next, *previous;
@@ -439,21 +449,22 @@ public:
     ElfSection *getFirstSection() { return sections.empty() ? NULL : sections.front(); }
     int getVPDiff() { return v_p_diff; }
     unsigned int getFileSize();
     unsigned int getMemSize();
     unsigned int getOffset();
     unsigned int getAddr();
 
     void addSection(ElfSection *section);
+    void removeSection(ElfSection *section);
 
     std::list<ElfSection *>::iterator begin() { return sections.begin(); }
     std::list<ElfSection *>::iterator end() { return sections.end(); }
 
-    ElfSegment *splitBefore(ElfSection *section);
+    void clear();
 private:
     unsigned int type;
     int v_p_diff; // Difference between physical and virtual address
     unsigned int flags;
     unsigned int align;
     std::list<ElfSection *> sections;
     // The following are only really used for PT_GNU_RELRO until something
     // better is found.
@@ -638,21 +649,27 @@ inline char Elf::getMachine() {
 
 inline unsigned int Elf::getSize() {
     ElfSection *section;
     for (section = shdr_section /* It's usually not far from the end */;
         section->getNext() != NULL; section = section->getNext());
     return section->getOffset() + section->getSize();
 }
 
-inline bool ElfSection::isInSegmentType(unsigned int type) {
+inline ElfSegment *ElfSection::getSegmentByType(unsigned int type) {
     for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
         if ((*seg)->getType() == type)
-            return true;
-    return false;
+            return *seg;
+    return NULL;
+}
+
+inline void ElfSection::insertInSegments(std::vector<ElfSegment *> &segs) {
+    for (std::vector<ElfSegment *>::iterator it = segs.begin(); it != segs.end(); ++it) {
+        (*it)->addSection(this);
+    }
 }
 
 inline ElfLocation::ElfLocation(ElfSection *section, unsigned int off, enum position pos)
 : section(section) {
     if ((pos == ABSOLUTE) && section)
         offset = off - section->getAddr();
     else
         offset = off;
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/816253.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <script>
+            window.onload = function() {
+                setInterval(
+                    function next_step() {
+                        var style = document.createElement('style');
+                        style.innerHTML = "{ }";
+                        document.getElementsByTagName("*")[ 7 ].appendChild(style);
+                        window.dump('.');
+                    }, 10);
+            }
+        </script>
+    </head>
+    <body>
+        <div id="console"></div>
+        <div id="parentDiv">
+            <div id="left-to-right" dir="auto" class="testElement">
+                <input type="text" value="מקור השם עברית">Test test test
+            </div>
+        </div>
+        <script id="des">
+            var el = document.getElementById("left-to-right");
+            document.defaultView.getComputedStyle(el, null).getPropertyValue('border-right-color');
+
+            document.getElementById("parentDiv").style.display = "none";
+        </script>
+
+    </body>
+</html>
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -111,8 +111,9 @@ load 715056.html
 load 741163-1.html
 load 766426.html
 load 771639.html
 load 752226-1.html
 load 752226-2.html
 HTTP(..) load xhr_abortinprogress.html
 load 786854.html
 load xhr_empty_datauri.html
+load 816253.html
--- a/content/base/src/DirectionalityUtils.cpp
+++ b/content/base/src/DirectionalityUtils.cpp
@@ -727,16 +727,19 @@ void SetAncestorDirectionIfAuto(nsINode*
               child = child->GetNextNonChildNode(parent);
               continue;
             }
 
             if (child == directionWasSetByTextNode) {
               // we found the node that set the element's direction after our
               // text node, so we need to reset the direction
               resetDirection = true;
+              nsTextNodeDirectionalityMap::RemoveElementFromMap(
+                directionWasSetByTextNode, parent
+              );
               break;
             }
 
             child = child->GetNextNode(parent);
           }
         }
       }
 
--- a/content/base/src/nsObjectLoadingContent.h
+++ b/content/base/src/nsObjectLoadingContent.h
@@ -126,17 +126,17 @@ class nsObjectLoadingContent : public ns
      * Called by nsDocument so we may suspend plugins in inactive documents)
      */
     void NotifyOwnerDocumentActivityChanged();
 
     /**
      * Used by pluginHost to know if we're loading with a channel, so it
      * will not open its own.
      */
-    bool SrcStreamLoading() { return mSrcStreamLoading; };
+    bool SrcStreamLoading() { return mSrcStreamLoading; }
 
   protected:
     /**
      * Begins loading the object when called
      *
      * Attributes of |this| QI'd to nsIContent will be inspected, depending on
      * the node type. This function currently assumes it is a <applet>,
      * <object>, or <embed> tag.
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -5453,28 +5453,28 @@ nsEventStateManager::WheelPrefs::Init(
   nsAutoCString prefNameZ(basePrefName);
   prefNameZ.AppendLiteral("delta_multiplier_z");
   mMultiplierZ[aIndex] =
     static_cast<double>(Preferences::GetInt(prefNameZ.get(), 100)) / 100;
 
   nsAutoCString prefNameAction(basePrefName);
   prefNameAction.AppendLiteral("action");
   int32_t action = Preferences::GetInt(prefNameAction.get(), ACTION_SCROLL);
-  if (action < ACTION_NONE || action > ACTION_LAST) {
+  if (action < int32_t(ACTION_NONE) || action > int32_t(ACTION_LAST)) {
     NS_WARNING("Unsupported action pref value, replaced with 'Scroll'.");
     action = ACTION_SCROLL;
   }
   mActions[aIndex] = static_cast<Action>(action);
 
   // Compute action values overridden by .override_x pref.
   // At present, override is possible only for the x-direction
   // because this pref is introduced mainly for tilt wheels.
   prefNameAction.AppendLiteral(".override_x");
   int32_t actionOverrideX = Preferences::GetInt(prefNameAction.get(), -1);
-  if (actionOverrideX < -1 || actionOverrideX > ACTION_LAST) {
+  if (actionOverrideX < -1 || actionOverrideX > int32_t(ACTION_LAST)) {
     NS_WARNING("Unsupported action override pref value, didn't override.");
     actionOverrideX = -1;
   }
   mOverriddenActionsX[aIndex] = (actionOverrideX == -1)
                               ? static_cast<Action>(action)
                               : static_cast<Action>(actionOverrideX);
 }
 
--- a/content/media/webrtc/MediaEngine.h
+++ b/content/media/webrtc/MediaEngine.h
@@ -26,34 +26,34 @@ enum MediaEngineState {
   kStarted,
   kStopped,
   kReleased
 };
 
 class MediaEngine
 {
 public:
-  virtual ~MediaEngine() {};
+  virtual ~MediaEngine() {}
 
   /* Populate an array of video sources in the nsTArray. Also include devices
    * that are currently unavailable. */
   virtual void EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSource> >*) = 0;
 
   /* Populate an array of audio sources in the nsTArray. Also include devices
    * that are currently unavailable. */
   virtual void EnumerateAudioDevices(nsTArray<nsRefPtr<MediaEngineAudioSource> >*) = 0;
 };
 
 /**
  * Common abstract base class for audio and video sources.
  */
 class MediaEngineSource : public nsISupports
 {
 public:
-  virtual ~MediaEngineSource() {};
+  virtual ~MediaEngineSource() {}
 
   /* Populate the human readable name of this device in the nsAString */
   virtual void GetName(nsAString&) = 0;
 
   /* Populate the UUID of this device in the nsAString */
   virtual void GetUUID(nsAString&) = 0;
 
   /* This call reserves but does not start the device. */
@@ -109,27 +109,27 @@ struct MediaEngineVideoOptions {
   uint32_t mHeight;
   uint32_t mMaxFPS;
   MediaEngineVideoCodecType codecType;
 };
 
 class MediaEngineVideoSource : public MediaEngineSource
 {
 public:
-  virtual ~MediaEngineVideoSource() {};
+  virtual ~MediaEngineVideoSource() {}
 
   /* Return a MediaEngineVideoOptions struct with appropriate values for all
    * fields. */
   virtual const MediaEngineVideoOptions *GetOptions() = 0;
 };
 
 /**
  * Audio source and friends.
  */
 class MediaEngineAudioSource : public MediaEngineSource
 {
 public:
-  virtual ~MediaEngineAudioSource() {};
+  virtual ~MediaEngineAudioSource() {}
 };
 
 }
 
 #endif /* MEDIAENGINE_H_ */
--- a/content/svg/content/src/DOMSVGLength.h
+++ b/content/svg/content/src/DOMSVGLength.h
@@ -90,17 +90,17 @@ public:
 
   ~DOMSVGLength() {
     // Our mList's weak ref to us must be nulled out when we die. If GC has
     // unlinked us using the cycle collector code, then that has already
     // happened, and mList is null.
     if (mList) {
       mList->mItems[mListIndex] = nullptr;
     }
-  };
+  }
 
   /**
    * Create an unowned copy of an owned length. The caller is responsible for
    * the first AddRef().
    */
   DOMSVGLength* Copy() {
     NS_ASSERTION(mList, "unexpected caller");
     DOMSVGLength *copy = new DOMSVGLength();
--- a/content/svg/content/src/DOMSVGLengthList.h
+++ b/content/svg/content/src/DOMSVGLengthList.h
@@ -66,17 +66,17 @@ public:
 
   ~DOMSVGLengthList() {
     // Our mAList's weak ref to us must be nulled out when we die. If GC has
     // unlinked us using the cycle collector code, then that has already
     // happened, and mAList is null.
     if (mAList) {
       ( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nullptr;
     }
-  };
+  }
 
   virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                bool *triedToWrap);
 
   nsISupports* GetParentObject()
   {
     return static_cast<nsIContent*>(Element());
   }
--- a/content/svg/content/src/DOMSVGNumber.h
+++ b/content/svg/content/src/DOMSVGNumber.h
@@ -65,17 +65,17 @@ public:
 
   ~DOMSVGNumber() {
     // Our mList's weak ref to us must be nulled out when we die. If GC has
     // unlinked us using the cycle collector code, then that has already
     // happened, and mList is null.
     if (mList) {
       mList->mItems[mListIndex] = nullptr;
     }
-  };
+  }
 
   /**
    * Create an unowned copy. The caller is responsible for the first AddRef().
    */
   DOMSVGNumber* Clone() {
     DOMSVGNumber *clone = new DOMSVGNumber();
     clone->mValue = ToSVGNumber();
     return clone;
--- a/content/svg/content/src/DOMSVGTransform.h
+++ b/content/svg/content/src/DOMSVGTransform.h
@@ -76,17 +76,17 @@ public:
     NS_ABORT_IF_FALSE(!mMatrixTearoff, "Matrix tear-off pointer not cleared."
         " Transform being destroyed before matrix?");
     // Our mList's weak ref to us must be nulled out when we die. If GC has
     // unlinked us using the cycle collector code, then that has already
     // happened, and mList is null.
     if (mList) {
       mList->mItems[mListIndex] = nullptr;
     }
-  };
+  }
 
   /**
    * Create an unowned copy of an owned transform. The caller is responsible for
    * the first AddRef().
    */
   DOMSVGTransform* Clone() {
     NS_ASSERTION(mList, "unexpected caller");
     return new DOMSVGTransform(InternalItem());
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -5118,18 +5118,18 @@ nsSVGFELightingElement::Filter(nsSVGFilt
 
       if (spotLight) {
         float S[3];
         S[0] = pointsAt[0] - lightPos[0];
         S[1] = pointsAt[1] - lightPos[1];
         S[2] = pointsAt[2] - lightPos[2];
         NORMALIZE(S);
         float dot = -DOT(L, S);
-        if (dot < cosConeAngle) dot = 0;
         float tmp = pow(dot, specularExponent);
+        if (dot < cosConeAngle) tmp = 0;
         color = NS_RGB(uint8_t(NS_GET_R(lightColor) * tmp),
                        uint8_t(NS_GET_G(lightColor) * tmp),
                        uint8_t(NS_GET_B(lightColor) * tmp));
       } else {
         color = lightColor;
       }
 
       LightPixel(N, L, color, targetData + index);
@@ -5978,17 +5978,17 @@ nsSVGFEDisplacementMapElement::Filter(ns
   int32_t width = instance->GetSurfaceWidth();
   int32_t height = instance->GetSurfaceHeight();
 
   uint8_t* sourceData = aSources[0]->mImage->Data();
   uint8_t* displacementData = aSources[1]->mImage->Data();
   uint8_t* targetData = aTarget->mImage->Data();
   uint32_t stride = aTarget->mImage->Stride();
 
-  static uint8_t dummyData[4] = { 0, 0, 0, 0 };
+  static const uint8_t dummyData[4] = { 0, 0, 0, 0 };
 
   static const uint16_t channelMap[5] = {
                              0,
                              GFX_ARGB32_OFFSET_R,
                              GFX_ARGB32_OFFSET_G,
                              GFX_ARGB32_OFFSET_B,
                              GFX_ARGB32_OFFSET_A };
   uint16_t xChannel = channelMap[mEnumAttributes[CHANNEL_X].GetAnimValue()];
@@ -6005,17 +6005,17 @@ nsSVGFEDisplacementMapElement::Filter(ns
         NSToIntFloor(scaleOver255 * displacementData[targIndex + xChannel] +
                 scaleAdjustment);
       int32_t sourceY = y +
         NSToIntFloor(scaleOver255 * displacementData[targIndex + yChannel] +
                 scaleAdjustment);
 
       bool outOfBounds = sourceX < 0 || sourceX >= width ||
                          sourceY < 0 || sourceY >= height;
-      uint8_t* data;
+      const uint8_t* data;
       int32_t multiplier;
       if (outOfBounds) {
         data = dummyData;
         multiplier = 0;
       } else {
         data = sourceData;
         multiplier = 1;
       }
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -226,44 +226,16 @@ nsSVGSVGElement::GetWidth(nsIDOMSVGAnima
 
 /* readonly attribute nsIDOMSVGAnimatedLength height; */
 NS_IMETHODIMP
 nsSVGSVGElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight)
 {
   return mLengthAttributes[HEIGHT].ToDOMAnimatedLength(aHeight, this);
 }
 
-/* attribute DOMString contentScriptType; */
-NS_IMETHODIMP
-nsSVGSVGElement::GetContentScriptType(nsAString & aContentScriptType)
-{
-  NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetContentScriptType");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-NS_IMETHODIMP
-nsSVGSVGElement::SetContentScriptType(const nsAString & aContentScriptType)
-{
-  NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetContentScriptType");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* attribute DOMString contentStyleType; */
-NS_IMETHODIMP
-nsSVGSVGElement::GetContentStyleType(nsAString & aContentStyleType)
-{
-  NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetContentStyleType");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-NS_IMETHODIMP
-nsSVGSVGElement::SetContentStyleType(const nsAString & aContentStyleType)
-{
-  NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetContentStyleType");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 /* readonly attribute nsIDOMSVGRect viewport; */
 NS_IMETHODIMP
 nsSVGSVGElement::GetViewport(nsIDOMSVGRect * *aViewport)
 {
   // XXX
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -136,17 +136,17 @@ public:
   NS_IMETHOD GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
   {
     nsresult rv;
     *aStyle = static_cast<nsXULElement*>(mElement.get())->GetStyle(&rv);
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ADDREF(*aStyle);
     return NS_OK;
   }
-  NS_FORWARD_NSIFRAMELOADEROWNER(static_cast<nsXULElement*>(mElement.get())->);
+  NS_FORWARD_NSIFRAMELOADEROWNER(static_cast<nsXULElement*>(mElement.get())->)
 private:
   nsCOMPtr<nsIDOMXULElement> mElement;
 };
 
 NS_IMPL_CYCLE_COLLECTION_1(nsXULElementTearoff, mElement)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULElementTearoff)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULElementTearoff)
--- a/dom/apps/src/PermissionsInstaller.jsm
+++ b/dom/apps/src/PermissionsInstaller.jsm
@@ -42,17 +42,17 @@ function debug(aMsg) {
 
 this.PermissionsTable =  { geolocation: {
                              app: PROMPT_ACTION,
                              privileged: PROMPT_ACTION,
                              certified: ALLOW_ACTION
                            },
                            camera: {
                              app: DENY_ACTION,
-                             privileged: PROMPT_ACTION,
+                             privileged: DENY_ACTION,
                              certified: ALLOW_ACTION
                            },
                            alarms: {
                              app: ALLOW_ACTION,
                              privileged: ALLOW_ACTION,
                              certified: ALLOW_ACTION
                            },
                            "tcp-socket": {
@@ -230,16 +230,21 @@ this.PermissionsTable =  { geolocation: 
                            },
                            audio: {
                              app: DENY_ACTION,
                              privileged: ALLOW_ACTION,
                              certified: ALLOW_ACTION,
                              channels: ["normal", "content", "notification",
                                "alarm", "telephony", "ringer", "publicnotification"]
                            },
+                           "open-remote-window": {
+                             app: DENY_ACTION,
+                             privileged: DENY_ACTION,
+                             certified: ALLOW_ACTION
+                           },
                          };
 
 /**
  * Append access modes to the permission name as suffixes.
  *   e.g. permission name 'contacts' with ['read', 'write'] =
  *   ['contacts-read', contacts-write']
  * @param string aPermName
  * @param array aAccess
--- a/dom/audiochannel/AudioChannelAgent.cpp
+++ b/dom/audiochannel/AudioChannelAgent.cpp
@@ -5,30 +5,26 @@
 #include "AudioChannelAgent.h"
 #include "AudioChannelCommon.h"
 #include "AudioChannelService.h"
 
 using namespace mozilla::dom;
 
 NS_IMPL_ISUPPORTS1(AudioChannelAgent, nsIAudioChannelAgent)
 
-static nsRefPtr<AudioChannelService> gAudioChannelService;
-
 AudioChannelAgent::AudioChannelAgent()
   : mCallback(nullptr)
   , mAudioChannelType(AUDIO_AGENT_CHANNEL_ERROR)
   , mIsRegToService(false)
   , mVisible(true)
 {
-  gAudioChannelService = AudioChannelService::GetAudioChannelService();
 }
 
 AudioChannelAgent::~AudioChannelAgent()
 {
-  gAudioChannelService = nullptr;
 }
 
 /* readonly attribute long audioChannelType; */
 NS_IMETHODIMP AudioChannelAgent::GetAudioChannelType(int32_t *aAudioChannelType)
 {
   *aAudioChannelType = mAudioChannelType;
   return NS_OK;
 }
@@ -63,54 +59,58 @@ NS_IMETHODIMP AudioChannelAgent::Init(in
   mAudioChannelType = channelType;
   mCallback = callback;
   return NS_OK;
 }
 
 /* boolean startPlaying (); */
 NS_IMETHODIMP AudioChannelAgent::StartPlaying(bool *_retval)
 {
+  AudioChannelService *service = AudioChannelService::GetAudioChannelService();
   if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
-      gAudioChannelService == nullptr) {
+      service == nullptr) {
     return NS_ERROR_FAILURE;
   }
 
-  gAudioChannelService->RegisterAudioChannelAgent(this,
+  service->RegisterAudioChannelAgent(this,
     static_cast<AudioChannelType>(mAudioChannelType));
-  *_retval = !gAudioChannelService->GetMuted(static_cast<AudioChannelType>(mAudioChannelType), !mVisible);
+  *_retval = !service->GetMuted(static_cast<AudioChannelType>(mAudioChannelType), !mVisible);
   mIsRegToService = true;
   return NS_OK;
 }
 
 /* void stopPlaying (); */
 NS_IMETHODIMP AudioChannelAgent::StopPlaying(void)
 {
   if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
       mIsRegToService == false) {
     return NS_ERROR_FAILURE;
   }
 
-  gAudioChannelService->UnregisterAudioChannelAgent(this);
+  AudioChannelService *service = AudioChannelService::GetAudioChannelService();
+  service->UnregisterAudioChannelAgent(this);
   mIsRegToService = false;
   return NS_OK;
 }
 
 /* void setVisibilityState (in boolean visible); */
 NS_IMETHODIMP AudioChannelAgent::SetVisibilityState(bool visible)
 {
   bool oldVisibility = mVisible;
 
   mVisible = visible;
   if (mIsRegToService && oldVisibility != mVisible && mCallback != nullptr) {
-    mCallback->CanPlayChanged(!gAudioChannelService->GetMuted(static_cast<AudioChannelType>(mAudioChannelType),
+    AudioChannelService *service = AudioChannelService::GetAudioChannelService();
+    mCallback->CanPlayChanged(!service->GetMuted(static_cast<AudioChannelType>(mAudioChannelType),
        !mVisible));
   }
   return NS_OK;
 }
 
 void AudioChannelAgent::NotifyAudioChannelStateChanged()
 {
   if (mCallback != nullptr) {
-    mCallback->CanPlayChanged(!gAudioChannelService->GetMuted(static_cast<AudioChannelType>(mAudioChannelType),
+    AudioChannelService *service = AudioChannelService::GetAudioChannelService();
+    mCallback->CanPlayChanged(!service->GetMuted(static_cast<AudioChannelType>(mAudioChannelType),
       !mVisible));
   }
 }
 
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -98,17 +98,17 @@ public:
                                    const char* aURL,
                                    uint32_t aLineNo,
                                    uint32_t aVersion,
                                    bool aShared,
                                    bool aIsXBL,
                                    JSObject** aFunctionObject);
 
   virtual nsIScriptGlobalObject *GetGlobalObject();
-  inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; };
+  inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; }
 
   virtual JSContext* GetNativeContext();
   virtual JSObject* GetNativeGlobal();
   virtual nsresult InitContext();
   virtual bool IsContextInitialized();
 
   virtual void ScriptEvaluated(bool aTerminated);
   virtual void SetTerminationFunction(nsScriptTerminationFunc aFunc,
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -422,17 +422,17 @@ DOMInterfaces = {
 'WebGLActiveInfo': {
    'nativeType': 'mozilla::WebGLActiveInfo',
    'headerFile': 'WebGLContext.h',
    'wrapperCache': False
 },
 
 'WebGLBuffer': {
    'nativeType': 'mozilla::WebGLBuffer',
-   'headerFile': 'WebGLContext.h'
+   'headerFile': 'WebGLBuffer.h'
 },
 
 'WebGLExtensionCompressedTextureATC': {
    'nativeType': 'mozilla::WebGLExtensionCompressedTextureATC',
    'headerFile': 'WebGLExtensions.h'
 },
 
 'WebGLExtensionCompressedTexturePVRTC': {
@@ -472,56 +472,56 @@ DOMInterfaces = {
 
 'WebGLExtensionTextureFloat': {
    'nativeType': 'mozilla::WebGLExtensionTextureFloat',
    'headerFile': 'WebGLExtensions.h'
 },
 
 'WebGLFramebuffer': {
    'nativeType': 'mozilla::WebGLFramebuffer',
-   'headerFile': 'WebGLContext.h'
+   'headerFile': 'WebGLFramebuffer.h'
 },
 
 'WebGLProgram': {
    'nativeType': 'mozilla::WebGLProgram',
-   'headerFile': 'WebGLContext.h'
+   'headerFile': 'WebGLProgram.h'
 },
 
 'WebGLRenderbuffer': {
    'nativeType': 'mozilla::WebGLRenderbuffer',
-   'headerFile': 'WebGLContext.h'
+   'headerFile': 'WebGLRenderbuffer.h'
 },
 
 'WebGLRenderingContext': {
   'nativeType': 'mozilla::WebGLContext',
   'headerFile': 'WebGLContext.h',
   'resultNotAddRefed': [ 'canvas', 'getContextAttributes', 'getExtension',
                          'getAttachedShaders' ],
   'implicitJSContext': [ 'getSupportedExtensions' ],
 },
 
 'WebGLShader': {
    'nativeType': 'mozilla::WebGLShader',
-   'headerFile': 'WebGLContext.h'
+   'headerFile': 'WebGLShader.h'
 },
 
 'WebGLShaderPrecisionFormat': {
    'nativeType': 'mozilla::WebGLShaderPrecisionFormat',
-   'headerFile': 'WebGLContext.h',
+   'headerFile': 'WebGLShaderPrecisionFormat.h',
    'wrapperCache': False
 },
 
 'WebGLTexture': {
    'nativeType': 'mozilla::WebGLTexture',
-   'headerFile': 'WebGLContext.h'
+   'headerFile': 'WebGLTexture.h'
 },
 
 'WebGLUniformLocation': {
    'nativeType': 'mozilla::WebGLUniformLocation',
-   'headerFile': 'WebGLContext.h',
+   'headerFile': 'WebGLUniformLocation.h',
    'wrapperCache': False
 },
 
 'WebSocket': {
     'headerFile': 'WebSocket.h',
     'implicitJSContext': [ 'constructor' ]
 },
 
--- a/dom/icc/interfaces/SimToolKit.idl
+++ b/dom/icc/interfaces/SimToolKit.idl
@@ -313,16 +313,29 @@ dictionary MozStkPlayTone
   /**
    * Need to vibrate or not.
    * true: vibrate alert, if available, with the tone.
    * false: use of vibrate alert is up to the ME.
    */
   boolean isVibrate;
 };
 
+dictionary MozStkProvideLocalInfo
+{
+  /**
+   * Indicate which local information is required.
+   * It shall be one of following:
+   *  - nsIDOMMozIccManager.STK_LOCAL_INFO_LOCATION_INFO
+   *  - nsIDOMMozIccManager.STK_LOCAL_INFO_IMEI
+   *  - nsIDOMMozIccManager.STK_LOCAL_INFO_DATE_TIME_ZONE
+   *  - nsIDOMMozIccManager.STK_LOCAL_INFO_LANGUAGE
+   */
+  unsigned short localInfoType;
+};
+
 dictionary MozStkLocationEvent
 {
   /**
    * The type of this event.
    * It shall be nsIDOMMozIccManager.STK_EVENT_TYPE_LOCATION_STATUS;
    */
   unsigned short eventType;
 
@@ -398,16 +411,20 @@ dictionary MozStkCommand
    * - STK_CMD_PLAY_TONE
    * options is MozStkPlayTone.
    *
    * When typeOfCommand is
    * - STK_CMD_POLL_INTERVAL
    * options is MozStkDuration.
    *
    * When typeOfCommand is
+   * - STK_CMD_PROVIDE_LOCAL_INFO
+   * options is MozStkProvideLocalInfo.
+   *
+   * When typeOfCommand is
    * - STK_CMD_POLL_OFF
    * options is null.
    *
    * When typeOfCommand is
    * - STK_CMD_REFRESH
    * options is null.
    */
   jsval options;
@@ -453,16 +470,23 @@ dictionary MozStkResponse
    * User has confirmed or rejected the call during STK_CMD_CALL_SET_UP.
    *
    * @see RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM
    *
    * true: Confirmed by User.
    * false: Rejected by User.
    */
   boolean hasConfirmed;
+
+  /**
+   * The response for STK_CMD_PROVIDE_LOCAL_INFO
+   *
+   * @see MozStkLocalInfo
+   */
+  jsval localInfo;
 };
 
 dictionary MozStkCallEvent
 {
   /**
    * The type of this event.
    * It shall be one of following:
    *     - nsIDOMMozIccManager.STK_EVENT_TYPE_MT_CALL,
@@ -488,8 +512,37 @@ dictionary MozStkCallEvent
 
   /**
    * This field is available in Call Disconnected event to indicate the cause
    * of disconnection. The cause string is passed to gaia through the error
    * listener of nsIDOMCallEvent. Null if there's no error.
    */
   DOMString error;
 };
+
+dictionary MozStkLocalInfo
+{
+  /**
+   * IMEI information
+   */
+  DOMString imei;
+
+  /**
+   * Location Information
+   *
+   * @see MozStkLocationInfo.
+   */
+  jsval locationInfo;
+
+  /**
+   * Date information
+   *
+   * @see Date
+   */
+  jsval date;
+
+  /**
+   * Language Information
+   *
+   * @see ISO 639-1, Alpha-2 code
+   */
+  DOMString language;
+};
--- a/dom/icc/interfaces/nsIDOMIccManager.idl
+++ b/dom/icc/interfaces/nsIDOMIccManager.idl
@@ -40,16 +40,17 @@ interface nsIDOMMozIccManager : nsIDOMEv
   const unsigned short STK_CMD_SEND_DTMF             = 0x14;
   const unsigned short STK_CMD_LAUNCH_BROWSER        = 0x15;
   const unsigned short STK_CMD_PLAY_TONE             = 0x20;
   const unsigned short STK_CMD_DISPLAY_TEXT          = 0x21;
   const unsigned short STK_CMD_GET_INKEY             = 0x22;
   const unsigned short STK_CMD_GET_INPUT             = 0x23;
   const unsigned short STK_CMD_SELECT_ITEM           = 0x24;
   const unsigned short STK_CMD_SET_UP_MENU           = 0x25;
+  const unsigned short STK_CMD_PROVIDE_LOCAL_INFO    = 0x26;
   const unsigned short STK_CMD_SET_UP_IDLE_MODE_TEXT = 0x28;
 
   /**
    * STK Result code.
    *
    * @see TS 11.14, clause 12.12
    *
    * Results '0X' and '1X' indicate that the command has been performed.
@@ -190,16 +191,26 @@ interface nsIDOMMozIccManager : nsIDOMEv
   /**
    * Time unit
    */
   const unsigned short STK_TIME_UNIT_MINUTE       = 0x00;
   const unsigned short STK_TIME_UNIT_SECOND       = 0x01;
   const unsigned short STK_TIME_UNIT_TENTH_SECOND = 0x02;
 
   /**
+   * Local Information list
+   *
+   * @see TS 102.223, clause 8.6
+   */
+  const unsigned short STK_LOCAL_INFO_LOCATION_INFO  = 0x00;
+  const unsigned short STK_LOCAL_INFO_IMEI           = 0x01;
+  const unsigned short STK_LOCAL_INFO_DATE_TIME_ZONE = 0x03;
+  const unsigned short STK_LOCAL_INFO_LANGUAGE       = 0x04;
+
+  /**
    * Send the response back to ICC after an attempt to execute STK Proactive
    * Command.
    *
    * @param command
    *        Command received from ICC. See MozStkCommand.
    * @param response
    *        The response that will be sent to ICC.
    * @see MozStkResponse for the detail of response.
--- a/dom/icc/tests/marionette/test_stk_proactive_command.js
+++ b/dom/icc/tests/marionette/test_stk_proactive_command.js
@@ -12,19 +12,67 @@ function testDisplayTextGsm7BitEncoding(
   log("STK CMD " + JSON.stringify(cmd));
   is(cmd.typeOfCommand, icc.STK_CMD_DISPLAY_TEXT);
   is(cmd.options.userClear, true);
   is(cmd.options.text, "Saldo 2.04 E. Validez 20/05/13. ");
 
   runNextTest();
 }
 
+function testLocalInfoLocation(cmd) {
+  log("STK CMD " + JSON.stringify(cmd));
+  is(cmd.typeOfCommand, icc.STK_CMD_PROVIDE_LOCAL_INFO);
+  is(cmd.commandNumber, 0x01);
+  is(cmd.commandQualifier, icc.STK_LOCAL_INFO_LOCATION_INFO);
+  is(cmd.options.localInfoType, icc.STK_LOCAL_INFO_LOCATION_INFO);
+
+  runNextTest();
+}
+
+function testLocalInfoImei(cmd) {
+  log("STK CMD " + JSON.stringify(cmd));
+  is(cmd.typeOfCommand, icc.STK_CMD_PROVIDE_LOCAL_INFO);
+  is(cmd.commandNumber, 0x01);
+  is(cmd.commandQualifier, icc.STK_LOCAL_INFO_IMEI);
+  is(cmd.options.localInfoType, icc.STK_LOCAL_INFO_IMEI);
+
+  runNextTest();
+}
+
+function testLocalInfoDate(cmd) {
+  log("STK CMD " + JSON.stringify(cmd));
+  is(cmd.typeOfCommand, icc.STK_CMD_PROVIDE_LOCAL_INFO);
+  is(cmd.commandNumber, 0x01);
+  is(cmd.commandQualifier, icc.STK_LOCAL_INFO_DATE_TIME_ZONE);
+  is(cmd.options.localInfoType, icc.STK_LOCAL_INFO_DATE_TIME_ZONE);
+
+  runNextTest();
+}
+
+function testLocalInfoLanguage(cmd) {
+  log("STK CMD " + JSON.stringify(cmd));
+  is(cmd.typeOfCommand, icc.STK_CMD_PROVIDE_LOCAL_INFO);
+  is(cmd.commandNumber, 0x01);
+  is(cmd.commandQualifier, icc.STK_LOCAL_INFO_LANGUAGE);
+  is(cmd.options.localInfoType, icc.STK_LOCAL_INFO_LANGUAGE);
+
+  runNextTest();
+}
+
 let tests = [
   {command: "d0288103012180820281020d1d00d3309bfc06c95c301aa8e80259c3ec34b9ac07c9602f58ed159bb940",
    func: testDisplayTextGsm7BitEncoding},
+  {command: "d009810301260082028182",
+   func: testLocalInfoLocation},
+  {command: "d009810301260182028182",
+   func: testLocalInfoImei},
+  {command: "d009810301260382028182",
+   func: testLocalInfoDate},
+  {command: "d009810301260482028182",
+   func: testLocalInfoLanguage},
 ];
 
 let pendingEmulatorCmdCount = 0;
 function sendStkPduToEmulator(cmd, func) {
   ++pendingEmulatorCmdCount;
 
   runEmulatorCmd(cmd, function (result) {
     --pendingEmulatorCmdCount;
--- a/dom/interfaces/svg/nsIDOMSVGSVGElement.idl
+++ b/dom/interfaces/svg/nsIDOMSVGSVGElement.idl
@@ -17,17 +17,17 @@ interface nsIDOMSVGTransform;
 
 // undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
 %{C++
 #ifdef GetCurrentTime
 #undef GetCurrentTime
 #endif
 %}
 
-[scriptable, uuid(BEC06C4F-3EF7-486E-A8F5-F375EE5CB5A8)]
+[scriptable, uuid(4670a204-4ef1-455f-9595-9847b077c624)]
 interface nsIDOMSVGSVGElement
   : nsIDOMSVGElement
 /*
         The SVG DOM makes use of multiple interface inheritance.
         Since XPCOM only supports single interface inheritance,
         the best thing that we can do is to promise that whenever
         an object implements _this_ interface it will also
         implement the following interfaces. (We then have to QI to
@@ -42,20 +42,16 @@ interface nsIDOMSVGSVGElement
     nsIDOMSVGZoomAndPan,
     events::nsIDOMEventTarget,
 */
 { 
   readonly attribute nsIDOMSVGAnimatedLength x;
   readonly attribute nsIDOMSVGAnimatedLength y;
   readonly attribute nsIDOMSVGAnimatedLength width;
   readonly attribute nsIDOMSVGAnimatedLength height;
-  attribute DOMString         contentScriptType;
-      // raises DOMException on setting
-  attribute DOMString         contentStyleType;
-      // raises DOMException on setting
   readonly attribute nsIDOMSVGRect     viewport;
   readonly attribute float pixelUnitToMillimeterX;
   readonly attribute float pixelUnitToMillimeterY;
   readonly attribute float screenPixelToMillimeterX;
   readonly attribute float screenPixelToMillimeterY;
   readonly attribute boolean useCurrentView;
   readonly attribute nsIDOMSVGViewSpec currentView;
   attribute float currentScale;
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -279,16 +279,19 @@ TabChild::OnLocationChange(nsIWebProgres
   }
 
   nsCOMPtr<nsIDOMWindow> window;
   aWebProgress->GetDOMWindow(getter_AddRefs(window));
   if (!window) {
     return NS_OK;
   }
 
+  nsCOMPtr<nsIDOMWindowUtils> utils(do_GetInterface(window));
+  utils->SetIsFirstPaint(true);
+
   nsCOMPtr<nsIDOMDocument> progressDoc;
   window->GetDocument(getter_AddRefs(progressDoc));
   if (!progressDoc) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDOMDocument> domDoc;
   mWebNav->GetDocument(getter_AddRefs(domDoc));
@@ -458,30 +461,37 @@ TabChild::HandlePossibleViewportChange()
     oldScreenWidth = mInnerSize.width;
   }
 
   FrameMetrics metrics(mLastMetrics);
   metrics.mViewport = gfx::Rect(0.0f, 0.0f, viewportW, viewportH);
   metrics.mScrollableRect = gfx::Rect(0.0f, 0.0f, pageWidth, pageHeight);
   metrics.mCompositionBounds = nsIntRect(0, 0, mInnerSize.width, mInnerSize.height);
 
-  gfxSize intrinsicScale =
-      AsyncPanZoomController::CalculateIntrinsicScale(metrics);
-  // FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of
-  // 0.0 to mean "did not calculate a zoom".  In that case, we default
-  // it to the intrinsic scale.
-  if (viewportInfo.defaultZoom < 0.01f) {
-    viewportInfo.defaultZoom = intrinsicScale.width;
+  // Changing the zoom when we're not doing a first paint will get ignored
+  // by AsyncPanZoomController and causes a blurry flash.
+  bool isFirstPaint;
+  nsresult rv = utils->GetIsFirstPaint(&isFirstPaint);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  if (NS_FAILED(rv) || isFirstPaint) {
+    gfxSize intrinsicScale =
+        AsyncPanZoomController::CalculateIntrinsicScale(metrics);
+    // FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of
+    // 0.0 to mean "did not calculate a zoom".  In that case, we default
+    // it to the intrinsic scale.
+    if (viewportInfo.defaultZoom < 0.01f) {
+      viewportInfo.defaultZoom = intrinsicScale.width;
+    }
+    MOZ_ASSERT(viewportInfo.minZoom <= viewportInfo.defaultZoom &&
+               viewportInfo.defaultZoom <= viewportInfo.maxZoom);
+    // GetViewportInfo() returns a resolution-dependent scale factor.
+    // Convert that to a resolution-indepedent zoom.
+    metrics.mZoom = gfxSize(viewportInfo.defaultZoom / intrinsicScale.width,
+                            viewportInfo.defaultZoom / intrinsicScale.height);
   }
-  MOZ_ASSERT(viewportInfo.minZoom <= viewportInfo.defaultZoom &&
-             viewportInfo.defaultZoom <= viewportInfo.maxZoom);
-  // GetViewportInfo() returns a resolution-dependent scale factor.
-  // Convert that to a resolution-indepedent zoom.
-  metrics.mZoom = gfxSize(viewportInfo.defaultZoom / intrinsicScale.width,
-                          viewportInfo.defaultZoom / intrinsicScale.height);
 
   metrics.mDisplayPort = AsyncPanZoomController::CalculatePendingDisplayPort(
     // The page must have been refreshed in some way such as a new document or
     // new CSS viewport, so we know that there's no velocity, acceleration, and
     // we have no idea how long painting will take.
     metrics, gfx::Point(0.0f, 0.0f), gfx::Point(0.0f, 0.0f), 0.0);
   gfxSize resolution = AsyncPanZoomController::CalculateResolution(metrics);
   // XXX is this actually hysteresis?  This calculation is not well
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -249,23 +249,23 @@ class MediaDevice : public nsIMediaDevic
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMEDIADEVICE
 
   MediaDevice(MediaEngineVideoSource* aSource) {
     mSource = aSource;
     mType.Assign(NS_LITERAL_STRING("video"));
     mSource->GetName(mName);
-  };
+  }
   MediaDevice(MediaEngineAudioSource* aSource) {
     mSource = aSource;
     mType.Assign(NS_LITERAL_STRING("audio"));
     mSource->GetName(mName);
-  };
-  virtual ~MediaDevice() {};
+  }
+  virtual ~MediaDevice() {}
 
   MediaEngineSource* GetSource();
 private:
   nsString mName;
   nsString mType;
   nsRefPtr<MediaEngineSource> mSource;
 };
 
@@ -312,30 +312,30 @@ public:
     nsIGetUserMediaDevicesSuccessCallback* onSuccess,
     nsIDOMGetUserMediaErrorCallback* onError);
   void OnNavigation(uint64_t aWindowID);
 
 private:
   WindowTable *GetActiveWindows() {
     NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
     return &mActiveWindows;
-  };
+  }
 
   // Make private because we want only one instance of this class
   MediaManager()
   : mMediaThread(nullptr)
   , mMutex("mozilla::MediaManager")
   , mBackend(nullptr) {
     mActiveWindows.Init();
     mActiveCallbacks.Init();
-  };
+  }
 
   ~MediaManager() {
     delete mBackend;
-  };
+  }
 
   // ONLY access from MainThread so we don't need to lock
   WindowTable mActiveWindows;
   nsRefPtrHashtable<nsStringHashKey, nsRunnable> mActiveCallbacks;
   // Always exists
   nsCOMPtr<nsIThread> mMediaThread;
 
   Mutex mMutex;
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/crashtests/812785.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=812785
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Bug 812785 - WebRTC use-after-free crash</title>
+  <script type="application/javascript">
+    var pc1, pc2, pc1_offer, pc2_answer, localAudio, remoteAudio;
+
+    function onFailure(code) {
+      stop();
+    }
+
+    function stop() {
+      pc1.close(); pc1 = null;
+      pc2.close(); pc2 = null;
+
+      var index = localStorage.index || 0;
+      if (index < 5) {
+        localStorage.index = index + 1;
+        window.location.reload();
+      }
+      else {
+        finish();
+      }
+    }
+
+    function start() {
+      localAudio = document.getElementById("local");
+      remoteAudio = document.getElementById("remote");
+
+      var stream = localAudio.mozCaptureStreamUntilEnded();
+
+      pc1 = new mozRTCPeerConnection();
+      pc2 = new mozRTCPeerConnection();
+
+      pc1.addStream(stream);
+      pc1.createOffer(function (offer) {
+        pc1_offer = offer;
+        pc1.setLocalDescription(pc1_offer, function () {
+          pc2.setRemoteDescription(pc1_offer, function () {
+            pc2.createAnswer(function (answer) {
+              pc2_answer = answer;
+              pc2.setLocalDescription(pc2_answer, function () {
+                pc1.setRemoteDescription(pc2_answer, function step6() {
+                  stop();
+                }, onFailure);
+              }, onFailure);
+            }, onFailure);
+          }, onFailure);
+        }, onFailure);
+      }, onFailure);
+    }
+
+    function finish() {
+      delete localStorage["index"];
+
+      document.documentElement.removeAttribute("class");
+    }
+  </script>
+</head>
+
+<body onload="start()">
+  <audio id="local" controls autoplay><source type="audio/wav" src="" /></audio>
+  <audio id="remote" controls></audio>
+</body>
+</html>
+
--- a/dom/media/tests/crashtests/crashtests.list
+++ b/dom/media/tests/crashtests/crashtests.list
@@ -1,8 +1,9 @@
 default-preferences pref(media.peerconnection.enabled,true)
 
 load 780790.html
 load 791270.html
 load 791278.html
 load 791330.html
 load 801227.html
 load 802982.html
+load 812785.html
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -181,22 +181,30 @@ static PRCList sPendingAsyncCalls = PR_I
 // POST/GET stream type
 enum eNPPStreamTypeInternal {
   eNPPStreamTypeInternal_Get,
   eNPPStreamTypeInternal_Post
 };
 
 static NS_DEFINE_IID(kMemoryCID, NS_MEMORY_CID);
 
+PRIntervalTime NS_NotifyBeginPluginCall()
+{
+  nsNPAPIPluginInstance::BeginPluginCall();
+  return PR_IntervalNow();
+}
+
 // This function sends a notification using the observer service to any object
 // registered to listen to the "experimental-notify-plugin-call" subject.
 // Each "experimental-notify-plugin-call" notification carries with it the run
 // time value in milliseconds that the call took to execute.
 void NS_NotifyPluginCall(PRIntervalTime startTime) 
 {
+  nsNPAPIPluginInstance::EndPluginCall();
+
   PRIntervalTime endTime = PR_IntervalNow() - startTime;
   nsCOMPtr<nsIObserverService> notifyUIService =
     mozilla::services::GetObserverService();
   if (!notifyUIService)
     return;
 
   float runTimeInSeconds = float(endTime) / PR_TicksPerSecond();
   nsAutoString runTimeString;
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -195,16 +195,18 @@ nsNPAPIPluginInstance::~nsNPAPIPluginIns
   PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance dtor: this=%p\n",this));
 
   if (mMIMEType) {
     PR_Free((void *)mMIMEType);
     mMIMEType = nullptr;
   }
 }
 
+uint32_t nsNPAPIPluginInstance::gInPluginCalls = 0;
+
 void
 nsNPAPIPluginInstance::Destroy()
 {
   Stop();
   mPlugin = nullptr;
 
 #if MOZ_WIDGET_ANDROID
   if (mContentSurface)
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -265,16 +265,24 @@ public:
 
   // Called when the instance fails to instantiate beceause the Carbon
   // event model is not supported.
   void CarbonNPAPIFailure();
 
   // Returns the contents scale factor of the screen the plugin is drawn on.
   double GetContentsScaleFactor();
 
+  static bool InPluginCall() { return gInPluginCalls > 0; }
+  static void BeginPluginCall() { ++gInPluginCalls; }
+  static void EndPluginCall()
+  {
+    NS_ASSERTION(InPluginCall(), "Must be in plugin call");
+    --gInPluginCalls;
+  }
+
 protected:
 
   nsresult GetTagType(nsPluginTagType *result);
   nsresult GetAttributes(uint16_t& n, const char*const*& names,
                          const char*const*& values);
   nsresult GetParameters(uint16_t& n, const char*const*& names,
                          const char*const*& values);
   nsresult GetMode(int32_t *result);
@@ -359,11 +367,13 @@ private:
   std::map<void*, VideoInfo*> mVideos;
   bool mOnScreen;
 
   nsIntSize mCurrentSize;
 #endif
 
   // is this instance Java and affected by bug 750480?
   bool mHaveJavaC2PJSObjectQuirk;
+
+  static uint32_t gInPluginCalls;
 };
 
 #endif // nsNPAPIPluginInstance_h_
--- a/dom/plugins/base/nsPluginSafety.h
+++ b/dom/plugins/base/nsPluginSafety.h
@@ -9,16 +9,17 @@
 #include "npapi.h"
 #include "nsPluginHost.h"
 #include <prinrval.h>
 
 #if defined(XP_WIN)
 #define CALL_SAFETY_ON
 #endif
 
+PRIntervalTime NS_NotifyBeginPluginCall();
 void NS_NotifyPluginCall(PRIntervalTime);
 
 #ifdef CALL_SAFETY_ON
 
 #include "mozilla/Preferences.h"
 
 extern bool gSkipPluginSafeCalls;
 
@@ -26,70 +27,70 @@ extern bool gSkipPluginSafeCalls;
 PR_BEGIN_MACRO                                                     \
   gSkipPluginSafeCalls =                                           \
     ::mozilla::Preferences::GetBool("plugin.dont_try_safe_calls",  \
                                     gSkipPluginSafeCalls);         \
 PR_END_MACRO
 
 #define NS_TRY_SAFE_CALL_RETURN(ret, fun, pluginInst) \
 PR_BEGIN_MACRO                                     \
-  PRIntervalTime startTime = PR_IntervalNow();     \
+  PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
   if(gSkipPluginSafeCalls)                         \
     ret = fun;                                     \
   else                                             \
   {                                                \
     MOZ_SEH_TRY                                    \
     {                                              \
       ret = fun;                                   \
     }                                              \
-    MOZ_SEH_EXCEPT(true)                        \
+    MOZ_SEH_EXCEPT(true)                           \
     {                                              \
       nsresult res;                                \
       nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &res));\
       if(NS_SUCCEEDED(res) && (host != nullptr))    \
         static_cast<nsPluginHost*>(host.get())->HandleBadPlugin(nullptr, pluginInst); \
       ret = (NPError)NS_ERROR_FAILURE;             \
     }                                              \
   }                                                \
   NS_NotifyPluginCall(startTime);		   \
 PR_END_MACRO
 
 #define NS_TRY_SAFE_CALL_VOID(fun, pluginInst) \
 PR_BEGIN_MACRO                              \
-  PRIntervalTime startTime = PR_IntervalNow();     \
+  PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
   if(gSkipPluginSafeCalls)                  \
     fun;                                    \
   else                                      \
   {                                         \
     MOZ_SEH_TRY                             \
     {                                       \
       fun;                                  \
     }                                       \
-    MOZ_SEH_EXCEPT(true)                 \
+    MOZ_SEH_EXCEPT(true)                    \
     {                                       \
       nsresult res;                         \
       nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &res));\
       if(NS_SUCCEEDED(res) && (host != nullptr))\
         static_cast<nsPluginHost*>(host.get())->HandleBadPlugin(nullptr, pluginInst);\
     }                                       \
   }                                         \
   NS_NotifyPluginCall(startTime);		   \
 PR_END_MACRO
 
 #else // vanilla calls
 
 #define NS_TRY_SAFE_CALL_RETURN(ret, fun, pluginInst) \
 PR_BEGIN_MACRO                                     \
-  PRIntervalTime startTime = PR_IntervalNow();     \
+  PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
   ret = fun;                                       \
-  NS_NotifyPluginCall(startTime);		   \
+  NS_NotifyPluginCall(startTime);		               \
 PR_END_MACRO
 
-#define NS_TRY_SAFE_CALL_VOID(fun, pluginInst) \
-PR_BEGIN_MACRO                              \
-  PRIntervalTime startTime = PR_IntervalNow();     \
-  fun;                                      \
-  NS_NotifyPluginCall(startTime);		   \
+#define NS_TRY_SAFE_CALL_VOID(fun, pluginInst)     \
+PR_BEGIN_MACRO                                     \
+  PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
+  fun;                                             \
+  NS_NotifyPluginCall(startTime);		               \
 PR_END_MACRO
 
 #endif // CALL_SAFETY_ON
 
 #endif //nsPluginSafety_h_
--- a/dom/sms/tests/marionette/manifest.ini
+++ b/dom/sms/tests/marionette/manifest.ini
@@ -19,8 +19,9 @@ qemu = true
 ;[test_filter_number_multiple.js]
 [test_filter_received.js]
 [test_filter_sent.js]
 [test_filter_read.js]
 [test_filter_unread.js]
 [test_number_of_messages.js]
 [test_mark_msg_read.js]
 [test_mark_msg_read_error.js]
+[test_bug814761.js]
new file mode 100644
--- /dev/null
+++ b/dom/sms/tests/marionette/test_bug814761.js
@@ -0,0 +1,70 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 20000;
+
+SpecialPowers.setBoolPref("dom.sms.enabled", true);
+SpecialPowers.addPermission("sms", true, document);
+
+let sms = window.navigator.mozSms;
+
+// Note: 378 chars and below is fine, but 379 and above will cause the issue.
+// Sending first message works, but second one we get emulator callback but
+// the actual SMS is never received, so script will timeout waiting for the
+// sms.onreceived event. Also note that a single larger message (i.e. 1600
+// characters) works; so it is not a compounded send limit.
+let fromNumber = "5551110000";
+let msgLength = 379;
+let msgText = new Array(msgLength + 1).join('a');
+
+let pendingEmulatorCmdCount = 0;
+function sendSmsToEmulator(from, text) {
+  ++pendingEmulatorCmdCount;
+
+  let cmd = "sms send " + from + " " + text;
+  runEmulatorCmd(cmd, function (result) {
+    --pendingEmulatorCmdCount;
+
+    is(result[0], "OK", "Emulator response");
+  });
+}
+
+function firstIncomingSms() {
+  simulateIncomingSms(secondIncomingSms);
+}
+
+function secondIncomingSms() {
+  simulateIncomingSms(cleanUp);
+}
+
+function simulateIncomingSms(nextFunction) {
+  log("Simulating incoming multipart SMS (" + msgText.length
+      + " chars total).");
+
+  sms.onreceived = function onreceived(event) {
+    log("Received 'onreceived' smsmanager event.");
+    sms.onreceived = null;
+
+    let incomingSms = event.message;
+    ok(incomingSms, "incoming sms");
+    is(incomingSms.body, msgText, "msg body");
+
+    window.setTimeout(nextFunction, 0);
+  };
+
+  sendSmsToEmulator(fromNumber, msgText);
+}
+
+function cleanUp() {
+  if (pendingEmulatorCmdCount) {
+    window.setTimeout(cleanUp, 100);
+    return;
+  }
+
+  SpecialPowers.removePermission("sms", document);
+  SpecialPowers.clearUserPref("dom.sms.enabled");
+  finish();
+}
+
+// Start the test
+firstIncomingSms();
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -550,26 +550,37 @@ this.COMPREHENSIONTLV_TAG_SUBADDRESS = 0
 this.COMPREHENSIONTLV_TAG_SMS_TPDU = 0x0b;
 this.COMPREHENSIONTLV_TAG_TEXT_STRING = 0x0d;
 this.COMPREHENSIONTLV_TAG_TONE = 0x0e;
 this.COMPREHENSIONTLV_TAG_ITEM = 0x0f;
 this.COMPREHENSIONTLV_TAG_ITEM_ID = 0x10;
 this.COMPREHENSIONTLV_TAG_RESPONSE_LENGTH = 0x11;
 this.COMPREHENSIONTLV_TAG_FILE_LIST = 0x12;
 this.COMPREHENSIONTLV_TAG_LOCATION_INFO = 0x13;
+this.COMPREHENSIONTLV_TAG_IMEI = 0x14;
 this.COMPREHENSIONTLV_TAG_HELP_REQUEST = 0x15;
+this.COMPREHENSIONTLV_TAG_NMR = 0x16;
 this.COMPREHENSIONTLV_TAG_DEFAULT_TEXT = 0x17;
 this.COMPREHENSIONTLV_TAG_CAUSE = 0x1a;
 this.COMPREHENSIONTLV_TAG_LOCATION_STATUS = 0x1b;
 this.COMPREHENSIONTLV_TAG_TRANSACTION_ID = 0x1c;
 this.COMPREHENSIONTLV_TAG_EVENT_LIST = 0x19;
 this.COMPREHENSIONTLV_TAG_ICON_ID = 0x1e;
 this.COMPREHENSIONTLV_TAG_ICON_ID_LIST = 0x1f;
+this.COMPREHENSIONTLV_TAG_DATE_TIME_ZONE = 0x26;
 this.COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE = 0x2b;
+this.COMPREHENSIONTLV_TAG_LANGUAGE = 0x2d;
 this.COMPREHENSIONTLV_TAG_URL = 0x31;
+this.COMPREHENSIONTLV_TAG_ACCESS_TECH = 0x3f;
+this.COMPREHENSIONTLV_TAG_SERVICE_RECORD = 0x41;
+this.COMPREHENSIONTLV_TAG_IMEISV = 0x62;
+this.COMPREHENSIONTLV_TAG_BATTERY_STATE = 0x63;
+this.COMPREHENSIONTLV_TAG_NETWORK_SEARCH_MODE = 0x65;
+this.COMPREHENSIONTLV_TAG_MEID = 0x6d;
+this.COMPREHENSIONTLV_TAG_BROADCAST_NETWORK_INFO = 0x7a;
 
 // Tags for Service Provider Display Information TLV
 this.SPDI_TAG_SPDI = 0xa3;
 this.SPDI_TAG_PLMN_LIST = 0x80;
 
 // Device identifiers, see TS 11.14, clause 12.7
 this.STK_DEVICE_ID_KEYPAD = 0x01;
 this.STK_DEVICE_ID_DISPLAY = 0x02;
@@ -591,16 +602,17 @@ this.STK_CMD_SEND_SMS = 0x13;
 this.STK_CMD_SEND_DTMF = 0x14;
 this.STK_CMD_LAUNCH_BROWSER = 0x15;
 this.STK_CMD_PLAY_TONE = 0x20;
 this.STK_CMD_DISPLAY_TEXT = 0x21;
 this.STK_CMD_GET_INKEY = 0x22;
 this.STK_CMD_GET_INPUT = 0x23;
 this.STK_CMD_SELECT_ITEM = 0x24;
 this.STK_CMD_SET_UP_MENU = 0x25;
+this.STK_CMD_PROVIDE_LOCAL_INFO = 0x26;
 this.STK_CMD_SET_UP_IDLE_MODE_TEXT = 0x28;
 
 // STK Result code.
 // TS 11.14, clause 12.12
 
 // Results '0X' and '1X' indicate that the command has been performed.
 
 // Command performed successfully.
@@ -776,16 +788,33 @@ this.STK_TONE_TYPE_GENERAL_BEEP         
 this.STK_TONE_TYPE_POSITIVE_ACK_TONE        = 0x11;
 this.STK_TONE_TYPE_NEGATIVE_ACK_TONE        = 0x12;
 
 // Time unit.
 this.STK_TIME_UNIT_MINUTE       = 0x00;
 this.STK_TIME_UNIT_SECOND       = 0x01;
 this.STK_TIME_UNIT_TENTH_SECOND = 0x02;
 
+// Local Information type.
+this.STK_LOCAL_INFO_NNA = 0x00;
+this.STK_LOCAL_INFO_IMEI = 0x01;
+this.STK_LOCAL_INFO_NMR_FOR_NNA = 0x02;
+this.STK_LOCAL_INFO_DATE_TIME_ZONE = 0x03;
+this.STK_LOCAL_INFO_LANGUAGE = 0x04;
+this.STK_LOCAL_INFO_ACCESS_TECH = 0x06;
+this.STK_LOCAL_INFO_ESN = 0x07;
+this.STK_LOCAL_INFO_IMEISV = 0x08;
+this.STK_LOCAL_INFO_SEARCH_MODE = 0x09;
+this.STK_LOCAL_INFO_CHARGE_STATE = 0x0A;
+this.STK_LOCAL_INFO_MEID = 0x0B;
+this.STK_LOCAL_INFO_BROADCAST_NETWORK_INFO = 0x0D;
+this.STK_LOCAL_INFO_MULTIPLE_ACCESS_TECH = 0x0E;
+this.STK_LOCAL_INFO_INFO_FOR_MULTIPLE_ACCESS_TECH = 0x0F;
+this.STK_LOCAL_INFO_NMR_FOR_MULTIPLE_ACCESS_TECH = 0x10;
+
 /**
  * Supported Terminal Facilities.
  *
  * value = 1, supported.
  *         0, not supported.
  */
 this.STK_TERMINAL_SUPPORT_PROFILE_DOWNLOAD             = 1;
 this.STK_TERMINAL_SUPPORT_SMS_PP_DOWNLOAD              = 1;
@@ -815,28 +844,46 @@ this.STK_TERMINAL_SUPPORT_PROACTIVE_POLL
 this.STK_TERMINAL_SUPPORT_PROACTIVE_REFRESH            = 1;
 
 this.STK_TERMINAL_SUPPORT_PROACTIVE_SELECT_ITEM        = 1;
 this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SMS           = 1;
 this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SS            = 1;
 this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_USSD          = 1;
 this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_CALL        = 1;
 this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_MENU        = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO         = 0;
+this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO         = 1;
 this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR     = 0;
 
 this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_EVENT_LIST  = 1;
 this.STK_TERMINAL_SUPPORT_EVENT_MT_CALL                = 1;
 this.STK_TERMINAL_SUPPORT_EVENT_CALL_CONNECTED         = 1;
 this.STK_TERMINAL_SUPPORT_EVENT_CALL_DISCONNECTED      = 1;
 this.STK_TERMINAL_SUPPORT_EVENT_LOCATION_STATUS        = 1;
 this.STK_TERMINAL_SUPPORT_EVENT_USER_ACTIVITY          = 0;
 this.STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE  = 0;
 this.STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS     = 0;
 
+this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP   = 0;
+this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT  = 0;
+this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE    = 1;
+this.STK_TERMINAL_SUPPORT_GET_INKEY                    = 1;
+this.STK_TERMINAL_SUPPORT_SET_UP_IDLE_MODE_TEXT        = 1;
+this.STK_TERMINAL_SUPPORT_RUN_AT_COMMAND               = 0;
+this.STK_TERMINAL_SUPPORT_SET_UP_CALL                  = 1;
+this.STK_TERMINAL_SUPPORT_CALL_CONTROL_BY_NNA          = 0;
+
+this.STK_TERMINAL_SUPPORT_DISPLAY_TEXT                      = 1;
+this.STK_TERMINAL_SUPPORT_SEND_DTMF_COMMAND                 = 1;
+this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR          = 0;
+this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_LANGUAGE     = 1;
+this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_TIME_ADVANCE = 0;
+this.STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION   = 0;
+this.STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER          = 1;
+this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH  = 0;
+
 this.STK_TERMINAL_PROFILE_DOWNLOAD =
   (STK_TERMINAL_SUPPORT_PROFILE_DOWNLOAD << 0) |
   (STK_TERMINAL_SUPPORT_SMS_PP_DOWNLOAD  << 1) |
   (STK_TERMINAL_SUPPORT_CELL_BROADCAST_DATA_DOWNLOAD  << 2) |
   (STK_TERMINAL_SUPPORT_MENU_SELECTION << 3) |
   (STK_TERMINAL_SUPPORT_SIM_DATA_DOWNLOAD_ERROR << 4) |
   (STK_TERMINAL_SUPPORT_TIMER_EXPIRATION << 5) |
   (STK_TERMINAL_SUPPORT_USSD_IN_CALL_CONTROL << 6) |
@@ -877,26 +924,46 @@ this.STK_TERMINAL_PROFILE_EVENT =
   (STK_TERMINAL_SUPPORT_EVENT_MT_CALL << 1) |
   (STK_TERMINAL_SUPPORT_EVENT_CALL_CONNECTED << 2) |
   (STK_TERMINAL_SUPPORT_EVENT_CALL_DISCONNECTED << 3) |
   (STK_TERMINAL_SUPPORT_EVENT_LOCATION_STATUS << 4) |
   (STK_TERMINAL_SUPPORT_EVENT_USER_ACTIVITY << 5) |
   (STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE << 6) |
   (STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS << 7);
 
+this.STK_TERMINAL_PROFILE_PROACTIVE_3 =
+  (STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP << 0) |
+  (STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT << 1) |
+  (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE << 2) |
+  (STK_TERMINAL_SUPPORT_GET_INKEY << 3) |
+  (STK_TERMINAL_SUPPORT_SET_UP_IDLE_MODE_TEXT << 4) |
+  (STK_TERMINAL_SUPPORT_RUN_AT_COMMAND << 5) |
+  (STK_TERMINAL_SUPPORT_SET_UP_CALL << 6) |
+  (STK_TERMINAL_SUPPORT_CALL_CONTROL_BY_NNA << 7);
+
+this.STK_TERMINAL_PROFILE_PROACTIVE_4 =
+  (STK_TERMINAL_SUPPORT_DISPLAY_TEXT << 0) |
+  (STK_TERMINAL_SUPPORT_SEND_DTMF_COMMAND << 1) |
+  (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR << 2) |
+  (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_LANGUAGE << 3) |
+  (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_TIME_ADVANCE << 4) |
+  (STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION << 5) |
+  (STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER << 6) |
+  (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH << 7);
+
 this.STK_SUPPORTED_TERMINAL_PROFILE = [
   STK_TERMINAL_PROFILE_DOWNLOAD,
   STK_TERMINAL_PROFILE_OTHER,
   STK_TERMINAL_PROFILE_PROACTIVE_1,
   STK_TERMINAL_PROFILE_PROACTIVE_2,
   STK_TERMINAL_PROFILE_EVENT,
   0x00, // Event extension
   0x00, // Multiple card proactive commands
-  0x00, // Proactive Commands
-  0x00, // Proactive Commands
+  STK_TERMINAL_PROFILE_PROACTIVE_3,
+  STK_TERMINAL_PROFILE_PROACTIVE_4,
   0x00, // Softkey support
   0x00, // Softkey information
   0x00, // BIP proactive commands
   0x00, // BIP supported bearers
   0x00, // Screen height
   0x00, // Screen width
   0x00, // 16, Screen effects
   0x00, // 17, BIP supported transport interface
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -55,16 +55,19 @@ const TLV_COMMAND_DETAILS_SIZE = 5;
 const TLV_DEVICE_ID_SIZE = 4;
 const TLV_RESULT_SIZE = 3;
 const TLV_ITEM_ID_SIZE = 3;
 const TLV_HELP_REQUESTED_SIZE = 2;
 const TLV_EVENT_LIST_SIZE = 3;
 const TLV_LOCATION_STATUS_SIZE = 3;
 const TLV_LOCATION_INFO_GSM_SIZE = 9;
 const TLV_LOCATION_INFO_UMTS_SIZE = 11;
+const TLV_IMEI_SIZE = 10;
+const TLV_DATE_TIME_ZONE_SIZE = 9;
+const TLV_LANGUAGE_SIZE = 4;
 
 const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"];
 
 // MMI match groups
 const MMI_MATCH_GROUP_FULL_MMI = 1;
 const MMI_MATCH_GROUP_MMI_PROCEDURE = 2;
 const MMI_MATCH_GROUP_SERVICE_CODE = 3;
 const MMI_MATCH_GROUP_SIA = 5;
@@ -470,18 +473,19 @@ let Buf = {
    * @param incoming
    *        Uint8Array containing the incoming data.
    */
   writeToIncoming: function writeToIncoming(incoming) {
     // We don't have to worry about the head catching the tail since
     // we process any backlog in parcels immediately, before writing
     // new data to the buffer. So the only edge case we need to handle
     // is when the incoming data is larger than the buffer size.
-    if (incoming.length > this.INCOMING_BUFFER_LENGTH) {
-      this.growIncomingBuffer(incoming.length);
+    let minMustAvailableSize = incoming.length + this.readIncoming;
+    if (minMustAvailableSize > this.INCOMING_BUFFER_LENGTH) {
+      this.growIncomingBuffer(minMustAvailableSize);
     }
 
     // We can let the typed arrays do the copying if the incoming data won't
     // wrap around the edges of the circular buffer.
     let remaining = this.INCOMING_BUFFER_LENGTH - this.incomingWriteIndex;
     if (remaining >= incoming.length) {
       this.incomingBytes.set(incoming, this.incomingWriteIndex);
     } else {
@@ -580,16 +584,23 @@ let Buf = {
     let response_type = this.readUint32();
 
     let request_type, options;
     if (response_type == RESPONSE_TYPE_SOLICITED) {
       let token = this.readUint32();
       let error = this.readUint32();
 
       options = this.tokenRequestMap[token];
+      if (!options) {
+        if (DEBUG) {
+          debug("Suspicious uninvited request found: " + token + ". Ignored!");
+        }
+        return;
+      }
+
       delete this.tokenRequestMap[token];
       request_type = options.rilRequestType;
 
       options.rilRequestError = error;
       if (DEBUG) {
         debug("Solicited response for request type " + request_type +
               ", token " + token + ", error " + error);
       }
@@ -3113,21 +3124,23 @@ let RIL = {
     Buf.writeUint32(0);
     Buf.sendParcel();
   },
 
   /**
    * Send STK terminal response.
    *
    * @param command
+   * @param deviceIdentities
    * @param resultCode
    * @param [optional] itemIdentifier
    * @param [optional] input
    * @param [optional] isYesNo
    * @param [optional] hasConfirmed
+   * @param [optional] localInfo
    */
   sendStkTerminalResponse: function sendStkTerminalResponse(response) {
     if (response.hasConfirmed !== undefined) {
       this.stkHandleCallSetup(response);
       return;
     }
 
     let token = Buf.newParcel(REQUEST_STK_SEND_TERMINAL_RESPONSE);
@@ -3149,16 +3162,28 @@ let RIL = {
     }
 
     // 1 octets = 2 chars.
     let size = (TLV_COMMAND_DETAILS_SIZE +
                 TLV_DEVICE_ID_SIZE +
                 TLV_RESULT_SIZE +
                 (response.itemIdentifier ? TLV_ITEM_ID_SIZE : 0) +
                 (textLen ? textLen + 3 : 0)) * 2;
+    if (response.localInfo) {
+      let localInfo = response.localInfo;
+      size = size +
+             (((localInfo.locationInfo ?
+               (localInfo.locationInfo.gsmCellId > 0xffff ?
+                 TLV_LOCATION_INFO_UMTS_SIZE :
+                 TLV_LOCATION_INFO_GSM_SIZE) :
+               0) +
+             (localInfo.imei ? TLV_IMEI_SIZE : 0) +
+             (localInfo.date ? TLV_DATE_TIME_ZONE_SIZE : 0) +
+             (localInfo.language ? TLV_LANGUAGE_SIZE : 0)) * 2);
+    }
     Buf.writeUint32(size);
 
     // Command Details
     GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
                                COMPREHENSIONTLV_FLAG_CR);
     GsmPDUHelper.writeHexOctet(3);
     if (response.command) {
       GsmPDUHelper.writeHexOctet(command.commandNumber);
@@ -3233,16 +3258,50 @@ let RIL = {
             for (let i = 0; i < textLen; i++) {
               GsmPDUHelper.writeHexOctet(text.charCodeAt(i));
             }
             break;
         }
       }
     }
 
+    // Local Information
+    if (response.localInfo) {
+      let localInfo = response.localInfo;
+
+      // Location Infomation
+      if (localInfo.locationInfo) {
+        ComprehensionTlvHelper.writeLocationInfoTlv(localInfo.locationInfo);
+      }
+
+      // IMEI
+      if (localInfo.imei) {
+        let imei = localInfo.imei;
+        if(imei.length == 15) {
+          imei = imei + "0";
+        }
+
+        GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_IMEI);
+        GsmPDUHelper.writeHexOctet(8);
+        for (let i = 0; i < imei.length / 2; i++) {
+          GsmPDUHelper.writeHexOctet(parseInt(imei.substr(i * 2, 2), 16));
+        }
+      }
+
+      // Date and Time Zone
+      if (localInfo.date) {
+        ComprehensionTlvHelper.writeDateTimeZoneTlv(localInfo.date);
+      }
+
+      // Language
+      if (localInfo.language) {
+        ComprehensionTlvHelper.writeLanguageTlv(localInfo.language);
+      }
+    }
+
     Buf.writeUint32(0);
     Buf.sendParcel();
   },
 
   /**
    * Send STK Envelope(Menu Selection) command.
    *
    * @param itemIdentifier
@@ -6116,16 +6175,30 @@ let GsmPDUHelper = {
    * @return the corresponding BCD number.
    */
   octetToBCD: function octetToBCD(octet) {
     return ((octet & 0xf0) <= 0x90) * ((octet >> 4) & 0x0f) +
            ((octet & 0x0f) <= 0x09) * (octet & 0x0f) * 10;
   },
 
   /**
+   * Convert a BCD number to an octet (number)
+   *
+   * Only take two digits with absolute value.
+   *
+   * @param bcd
+   *
+   * @return the corresponding octet.
+   */
+  BCDToOctet: function BCDToOctet(bcd) {
+    bcd = Math.abs(bcd);
+    return ((bcd % 10) << 4) + (Math.floor(bcd / 10) % 10);
+  },
+
+  /**
    * Convert a semi-octet (number) to a GSM BCD char.
    */
   bcdChars: "0123456789*#,;",
   semiOctetToBcdChar: function semiOctetToBcdChar(semiOctet) {
     if (semiOctet >= 14) {
       throw new RangeError();
     }
 
@@ -6200,16 +6273,34 @@ let GsmPDUHelper = {
     }
     for (let i = 0; i < data.length; i += 2) {
       Buf.writeUint16(data.charCodeAt(i + 1));
       Buf.writeUint16(data.charCodeAt(i));
     }
   },
 
   /**
+   * Write numerical data as swapped nibble BCD.
+   * If the number of digit of data is even, add '0' at the beginning.
+   *
+   * @param data
+   *        Data to write (as a string or a number)
+   */
+  writeSwappedNibbleBCDNum: function writeSwappedNibbleBCDNum(data) {
+    data = data.toString();
+    if (data.length % 2) {
+      data = "0" + data;
+    }
+    for (let i = 0; i < data.length; i += 2) {
+      Buf.writeUint16(data.charCodeAt(i + 1));
+      Buf.writeUint16(data.charCodeAt(i));
+    }
+  },
+
+  /**
    * Read user data, convert to septets, look up relevant characters in a
    * 7-bit alphabet, and construct string.
    *
    * @param length
    *        Number of septets to read (*not* octets)
    * @param paddingBits
    *        Number of padding bits in the first byte of user data.
    * @param langIndex
@@ -7024,16 +7115,53 @@ let GsmPDUHelper = {
     let tzOffset = this.octetToBCD(tzOctet & ~0x08) * 15 * 60 * 1000;
     tzOffset = (tzOctet & 0x08) ? -tzOffset : tzOffset;
     timestamp -= tzOffset;
 
     return timestamp;
   },
 
   /**
+   * Write GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
+   *
+   * @see 3GPP TS 23.040 9.2.3.11
+   */
+  writeTimestamp: function writeTimestamp(date) {
+    this.writeSwappedNibbleBCDNum(date.getFullYear() - PDU_TIMESTAMP_YEAR_OFFSET);
+
+    // The value returned by getMonth() is an integer between 0 and 11.
+    // 0 is corresponds to January, 1 to February, and so on.
+    this.writeSwappedNibbleBCDNum(date.getMonth() + 1);
+    this.writeSwappedNibbleBCDNum(date.getDate());
+    this.writeSwappedNibbleBCDNum(date.getHours());
+    this.writeSwappedNibbleBCDNum(date.getMinutes());
+    this.writeSwappedNibbleBCDNum(date.getSeconds());
+
+    // the value returned by getTimezoneOffset() is the difference,
+    // in minutes, between UTC and local time.
+    // For example, if your time zone is UTC+10 (Australian Eastern Standard Time),
+    // -600 will be returned.
+    // In TS 23.040 9.2.3.11, the Time Zone field of TP-SCTS indicates
+    // the different between the local time and GMT.
+    // And expressed in quarters of an hours. (so need to divid by 15)
+    let zone = date.getTimezoneOffset() / 15;
+    let octet = this.BCDToOctet(zone);
+
+    // the bit3 of the Time Zone field represents the algebraic sign.
+    // (0: positive, 1: negative).
+    // For example, if the time zone is -0800 GMT,
+    // 480 will be returned by getTimezoneOffset().
+    // In this case, need to mark sign bit as 1. => 0x08
+    if (zone > 0) {
+      octet = octet | 0x08;
+    }
+    this.writeHexOctet(octet);
+  },
+
+  /**
    * User data can be 7 bit (default alphabet) data, 8 bit data, or 16 bit
    * (UCS2) data.
    *
    * @param msg
    *        message object for output.
    * @param length
    *        length of user data to read in octets.
    */
@@ -7733,16 +7861,19 @@ let StkCommandParamsFactory = {
         param = this.processMoreTime(cmdDetails, ctlvs);
         break;
       case STK_CMD_POLL_INTERVAL:
         param = this.processPollInterval(cmdDetails, ctlvs);
         break;
       case STK_CMD_POLL_OFF:
         param = this.processPollOff(cmdDetails, ctlvs);
         break;
+      case STK_CMD_PROVIDE_LOCAL_INFO:
+        param = this.processProvideLocalInfo(cmdDetails, ctlvs);
+        break;
       case STK_CMD_SET_UP_EVENT_LIST:
         param = this.processSetUpEventList(cmdDetails, ctlvs);
         break;
       case STK_CMD_SET_UP_MENU:
       case STK_CMD_SELECT_ITEM:
         param = this.processSelectItem(cmdDetails, ctlvs);
         break;
       case STK_CMD_DISPLAY_TEXT:
@@ -8140,16 +8271,31 @@ let StkCommandParamsFactory = {
     if (ctlv) {
       playTone.duration = ctlv.value;
     }
 
     // vibrate is only defined in TS 102.223
     playTone.isVibrate = (cmdDetails.commandQualifier & 0x01) != 0x00;
 
     return playTone;
+  },
+
+  /**
+   * Construct a param for Provide Local Information
+   *
+   * @param cmdDetails
+   *        The value object of CommandDetails TLV.
+   * @param ctlvs
+   *        The all TLVs in this proactive command.
+   */
+  processProvideLocalInfo: function processProvideLocalInfo(cmdDetails, ctlvs) {
+    let provideLocalInfo = {
+      localInfoType: cmdDetails.commandQualifier
+    };
+    return provideLocalInfo;
   }
 };
 
 let StkProactiveCmdHelper = {
   retrieve: function retrieve(tag, length) {
     switch (tag) {
       case COMPREHENSIONTLV_TAG_COMMAND_DETAILS:
         return this.retrieveCommandDetails(length);
@@ -8659,16 +8805,34 @@ let ComprehensionTlvHelper = {
 
     // TS 04.08, clause 10.5.4.11: ext bit = 1 + 7 bits for cause.
     // +-----------------+----------------------------------+
     // | Ext = 1 (1 bit) |          Cause (7 bits)          |
     // +-----------------+----------------------------------+
     GsmPDUHelper.writeHexOctet(0x80 | cause);
   },
 
+  writeDateTimeZoneTlv: function writeDataTimeZoneTlv(date) {
+    GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DATE_TIME_ZONE);
+    GsmPDUHelper.writeHexOctet(7);
+    GsmPDUHelper.writeTimestamp(date);
+  },
+
+  writeLanguageTlv: function writeLanguageTlv(language) {
+    GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LANGUAGE);
+    GsmPDUHelper.writeHexOctet(2);
+
+    // ISO 639-1, Alpha-2 code
+    // TS 123.038, clause 6.2.1, GSM 7 bit Default Alphabet
+    GsmPDUHelper.writeHexOctet(
+      PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT].indexOf(language[0]));
+    GsmPDUHelper.writeHexOctet(
+      PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT].indexOf(language[1]));
+  },
+
   getSizeOfLengthOctets: function getSizeOfLengthOctets(length) {
     if (length >= 0x10000) {
       return 4; // 0x83, len_1, len_2, len_3
     } else if (length >= 0x100) {
       return 3; // 0x82, len_1, len_2
     } else if (length >= 0x80) {
       return 2; // 0x81, len
     } else {
--- a/dom/system/gonk/tests/test_ril_worker_buf.js
+++ b/dom/system/gonk/tests/test_ril_worker_buf.js
@@ -77,16 +77,91 @@ add_test_incoming_parcel(null,
 
     do_check_throws(function over_read_handler() {
       // reads more than parcel size, should throw an error.
       buf.readUint8();
     },"Trying to read data beyond the parcel end!");
   }
 );
 
+// Test Bug 814761: buffer overwritten
+add_test(function test_incoming_parcel_buffer_overwritten() {
+  let worker = newWorker({
+    postRILMessage: function fakePostRILMessage(data) {
+      // do nothing
+    },
+    postMessage: function fakePostMessage(message) {
+      // do nothing
+    }
+  });
+
+  // A convenient alias.
+  let buf = worker.Buf;
+
+  // Allocate an array of specified size and set each of its elements to value.
+  function calloc(length, value) {
+    let array = new Array(length);
+    for (let i = 0; i < length; i++) {
+      array[i] = value;
+    }
+    return array;
+  }
+
+  // Do nothing in handleParcel().
+  let request = worker.REQUEST_REGISTRATION_STATE;
+  worker.RIL[request] = null;
+
+  // Prepare two parcels, whose sizes are both smaller than the incoming buffer
+  // size but larger when combined, to trigger the bug.
+  let pA_dataLength = buf.INCOMING_BUFFER_LENGTH / 2;
+  let pA = newIncomingParcel(-1,
+                             worker.RESPONSE_TYPE_UNSOLICITED,
+                             request,
+                             calloc(pA_dataLength, 1));
+  let pA_parcelSize = pA.length - worker.PARCEL_SIZE_SIZE;
+
+  let pB_dataLength = buf.INCOMING_BUFFER_LENGTH * 3 / 4;
+  let pB = newIncomingParcel(-1,
+                             worker.RESPONSE_TYPE_UNSOLICITED,
+                             request,
+                             calloc(pB_dataLength, 1));
+  let pB_parcelSize = pB.length - worker.PARCEL_SIZE_SIZE;
+
+  // First, send an incomplete pA and verifies related data pointer:
+  let p1 = pA.subarray(0, pA.length - 1);
+  worker.onRILMessage(p1);
+  // The parcel should not have been processed.
+  do_check_eq(buf.readAvailable, 0);
+  // buf.currentParcelSize should have been set because incoming data has more
+  // than 4 octets.
+  do_check_eq(buf.currentParcelSize, pA_parcelSize);
+  // buf.readIncoming should contains remaining unconsumed octets count.
+  do_check_eq(buf.readIncoming, p1.length - worker.PARCEL_SIZE_SIZE);
+  // buf.incomingWriteIndex should be ready to accept the last octet.
+  do_check_eq(buf.incomingWriteIndex, p1.length);
+
+  // Second, send the last octet of pA and whole pB. The Buf should now expand
+  // to cover both pA & pB.
+  let p2 = new Uint8Array(1 + pB.length);
+  p2.set(pA.subarray(pA.length - 1), 0);
+  p2.set(pB, 1);
+  worker.onRILMessage(p2);
+  // The parcels should have been both consumed.
+  do_check_eq(buf.readAvailable, 0);
+  // No parcel data remains.
+  do_check_eq(buf.currentParcelSize, 0);
+  // No parcel data remains.
+  do_check_eq(buf.readIncoming, 0);
+  // The Buf should now expand to cover both pA & pB.
+  do_check_eq(buf.incomingWriteIndex, pA.length + pB.length);
+
+  // end of incoming parcel's trip, let's do next test.
+  run_next_test();
+});
+
 // Test Buf.readUint8Array.
 add_test_incoming_parcel(null,
   function test_buf_readUint8Array(worker) {
     let buf = worker.Buf;
 
     let u8array = buf.readUint8Array(1);
     do_check_eq(u8array instanceof Uint8Array, true);
     do_check_eq(u8array.length, 1);
--- a/dom/system/gonk/tests/test_ril_worker_icc.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc.js
@@ -117,16 +117,85 @@ add_test(function test_write_dialling_nu
   len = 5;
   helper.writeDiallingNumber(number);
   do_check_eq(helper.readDiallingNumber(len), number);
 
   run_next_test();
 });
 
 /**
+ * Verify GsmPDUHelper.writeTimestamp
+ */
+add_test(function test_write_timestamp() {
+  let worker = newUint8Worker();
+  let helper = worker.GsmPDUHelper;
+
+  // current date
+  let dateInput = new Date();
+  let dateOutput = new Date();
+  helper.writeTimestamp(dateInput);
+  dateOutput.setTime(helper.readTimestamp());
+
+  do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
+  do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
+  do_check_eq(dateInput.getDate(), dateOutput.getDate());
+  do_check_eq(dateInput.getHours(), dateOutput.getHours());
+  do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
+  do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
+  do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
+
+  // 2034-01-23 12:34:56 -0800 GMT
+  let time = Date.UTC(2034, 1, 23, 12, 34, 56);
+  time = time - (8 * 60 * 60 * 1000);
+  dateInput.setTime(time);
+  helper.writeTimestamp(dateInput);
+  dateOutput.setTime(helper.readTimestamp());
+
+  do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
+  do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
+  do_check_eq(dateInput.getDate(), dateOutput.getDate());
+  do_check_eq(dateInput.getHours(), dateOutput.getHours());
+  do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
+  do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
+  do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
+
+  run_next_test();
+});
+
+/**
+ * Verify GsmPDUHelper.octectToBCD and GsmPDUHelper.BCDToOctet
+ */
+add_test(function test_octect_BCD() {
+  let worker = newUint8Worker();
+  let helper = worker.GsmPDUHelper;
+
+  // 23
+  let number = 23;
+  let octet = helper.BCDToOctet(number);
+  do_check_eq(helper.octetToBCD(octet), number);
+
+  // 56
+  number = 56;
+  octet = helper.BCDToOctet(number);
+  do_check_eq(helper.octetToBCD(octet), number);
+
+  // 0x23
+  octet = 0x23;
+  number = helper.octetToBCD(octet);
+  do_check_eq(helper.BCDToOctet(number), octet);
+
+  // 0x56
+  octet = 0x56;
+  number = helper.octetToBCD(octet);
+  do_check_eq(helper.BCDToOctet(number), octet);
+
+  run_next_test();
+});
+
+/**
  * Verify RIL.isICCServiceAvailable.
  */
 add_test(function test_is_icc_service_available() {
   let worker = newUint8Worker();
 
   function test_table(sst, geckoService, simEnabled, usimEnabled) {
     worker.RIL.iccInfo.sst = sst;
     worker.RIL.appType = CARD_APPTYPE_SIM;
@@ -577,8 +646,56 @@ add_test(function test_stk_proactive_com
   let ctlvs = berTlv.value;
   let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
   do_check_eq(tlv.value.commandNumber, 0x01);
   do_check_eq(tlv.value.typeOfCommand, STK_CMD_MORE_TIME);
   do_check_eq(tlv.value.commandQualifier, 0x00);
 
   run_next_test();
 });
+
+/**
+ * Verify Proactive Command : Provide Local Information
+ */
+add_test(function test_stk_proactive_command_provide_local_information() {
+  let worker = newUint8Worker();
+  let pduHelper = worker.GsmPDUHelper;
+  let berHelper = worker.BerTlvHelper;
+  let stkHelper = worker.StkProactiveCmdHelper;
+
+  // Verify IMEI
+  let local_info_1 = [
+    0xD0,
+    0x09,
+    0x81, 0x03, 0x01, 0x26, 0x01,
+    0x82, 0x02, 0x81, 0x82];
+
+  for (let i = 0; i < local_info_1.length; i++) {
+    pduHelper.writeHexOctet(local_info_1[i]);
+  }
+
+  let berTlv = berHelper.decode(local_info_1.length);
+  let ctlvs = berTlv.value;
+  let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
+  do_check_eq(tlv.value.commandNumber, 0x01);
+  do_check_eq(tlv.value.typeOfCommand, STK_CMD_PROVIDE_LOCAL_INFO);
+  do_check_eq(tlv.value.commandQualifier, STK_LOCAL_INFO_IMEI);
+
+  // Verify Date and Time Zone
+  let local_info_2 = [
+    0xD0,
+    0x09,
+    0x81, 0x03, 0x01, 0x26, 0x03,
+    0x82, 0x02, 0x81, 0x82];
+
+  for (let i = 0; i < local_info_2.length; i++) {
+    pduHelper.writeHexOctet(local_info_2[i]);
+  }
+
+  berTlv = berHelper.decode(local_info_2.length);
+  ctlvs = berTlv.value;
+  tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
+  do_check_eq(tlv.value.commandNumber, 0x01);
+  do_check_eq(tlv.value.typeOfCommand, STK_CMD_PROVIDE_LOCAL_INFO);
+  do_check_eq(tlv.value.commandQualifier, STK_LOCAL_INFO_DATE_TIME_ZONE);
+
+  run_next_test();
+});
--- a/editor/libeditor/html/nsWSRunObject.h
+++ b/editor/libeditor/html/nsWSRunObject.h
@@ -79,17 +79,17 @@ public:
     return *this;
   }
   WSType& operator|=(const WSType& aOther) {
     mEnum |= aOther.mEnum;
     return *this;
   }
 private:
   uint16_t mEnum;
-  void bool_conversion_helper() {};
+  void bool_conversion_helper() {}
 public:
   // Allow boolean conversion with no numeric conversion
   typedef void (WSType::*bool_type)();
   operator bool_type() const
   {
     return mEnum ? &WSType::bool_conversion_helper : nullptr;
   }
 };
--- a/gfx/2d/convolver.cpp
+++ b/gfx/2d/convolver.cpp
@@ -34,16 +34,28 @@
 #include "skia/SkTypes.h"
 
 // note: SIMD_SSE2 is not enabled because of bugs, apparently
 
 #if defined(SIMD_SSE2)
 #include <emmintrin.h>  // ARCH_CPU_X86_FAMILY was defined in build/config.h
 #endif
 
+#if defined(SK_CPU_LENDIAN)
+#define R_OFFSET_IDX 0
+#define G_OFFSET_IDX 1
+#define B_OFFSET_IDX 2
+#define A_OFFSET_IDX 3
+#else
+#define R_OFFSET_IDX 3
+#define G_OFFSET_IDX 2
+#define B_OFFSET_IDX 1
+#define A_OFFSET_IDX 0
+#endif
+
 namespace skia {
 
 namespace {
 
 // Converts the argument to an 8-bit unsigned value by clamping to the range
 // 0-255.
 inline unsigned char ClampTo8(int a) {
   if (static_cast<unsigned>(a) < 256)
@@ -157,37 +169,37 @@ void ConvolveHorizontally(const unsigned
     // Compute the first pixel in this row that the filter affects. It will
     // touch |filter_length| pixels (4 bytes each) after this.
     const unsigned char* row_to_filter = &src_data[filter_offset * 4];
 
     // Apply the filter to the row to get the destination pixel in |accum|.
     int accum[4] = {0};
     for (int filter_x = 0; filter_x < filter_length; filter_x++) {
       ConvolutionFilter1D::Fixed cur_filter = filter_values[filter_x];
-      accum[0] += cur_filter * row_to_filter[filter_x * 4 + 0];
-      accum[1] += cur_filter * row_to_filter[filter_x * 4 + 1];
-      accum[2] += cur_filter * row_to_filter[filter_x * 4 + 2];
+      accum[0] += cur_filter * row_to_filter[filter_x * 4 + R_OFFSET_IDX];
+      accum[1] += cur_filter * row_to_filter[filter_x * 4 + G_OFFSET_IDX];
+      accum[2] += cur_filter * row_to_filter[filter_x * 4 + B_OFFSET_IDX];
       if (has_alpha)
-        accum[3] += cur_filter * row_to_filter[filter_x * 4 + 3];
+        accum[3] += cur_filter * row_to_filter[filter_x * 4 + A_OFFSET_IDX];
     }
 
     // Bring this value back in range. All of the filter scaling factors
     // are in fixed point with kShiftBits bits of fractional part.
     accum[0] >>= ConvolutionFilter1D::kShiftBits;
     accum[1] >>= ConvolutionFilter1D::kShiftBits;
     accum[2] >>= ConvolutionFilter1D::kShiftBits;
     if (has_alpha)
       accum[3] >>= ConvolutionFilter1D::kShiftBits;
 
     // Store the new pixel.
-    out_row[out_x * 4 + 0] = ClampTo8(accum[0]);
-    out_row[out_x * 4 + 1] = ClampTo8(accum[1]);
-    out_row[out_x * 4 + 2] = ClampTo8(accum[2]);
+    out_row[out_x * 4 + R_OFFSET_IDX] = ClampTo8(accum[0]);
+    out_row[out_x * 4 + G_OFFSET_IDX] = ClampTo8(accum[1]);
+    out_row[out_x * 4 + B_OFFSET_IDX] = ClampTo8(accum[2]);
     if (has_alpha)
-      out_row[out_x * 4 + 3] = ClampTo8(accum[3]);
+      out_row[out_x * 4 + A_OFFSET_IDX] = ClampTo8(accum[3]);
   }
 }
 
 // Does vertical convolution to produce one output row. The filter values and
 // length are given in the first two parameters. These are applied to each
 // of the rows pointed to in the |source_data_rows| array, with each row
 // being |pixel_width| wide.
 //
@@ -204,54 +216,58 @@ void ConvolveVertically(const Convolutio
     // Compute the number of bytes over in each row that the current column
     // we're convolving starts at. The pixel will cover the next 4 bytes.
     int byte_offset = out_x * 4;
 
     // Apply the filter to one column of pixels.
     int accum[4] = {0};
     for (int filter_y = 0; filter_y < filter_length; filter_y++) {
       ConvolutionFilter1D::Fixed cur_filter = filter_values[filter_y];
-      accum[0] += cur_filter * source_data_rows[filter_y][byte_offset + 0];
-      accum[1] += cur_filter * source_data_rows[filter_y][byte_offset + 1];
-      accum[2] += cur_filter * source_data_rows[filter_y][byte_offset + 2];
+      accum[0] += cur_filter 
+	* source_data_rows[filter_y][byte_offset + R_OFFSET_IDX];
+      accum[1] += cur_filter 
+	* source_data_rows[filter_y][byte_offset + G_OFFSET_IDX];
+      accum[2] += cur_filter 
+	* source_data_rows[filter_y][byte_offset + B_OFFSET_IDX];
       if (has_alpha)
-        accum[3] += cur_filter * source_data_rows[filter_y][byte_offset + 3];
+        accum[3] += cur_filter 
+	  * source_data_rows[filter_y][byte_offset + A_OFFSET_IDX];
     }
 
     // Bring this value back in range. All of the filter scaling factors
     // are in fixed point with kShiftBits bits of precision.
     accum[0] >>= ConvolutionFilter1D::kShiftBits;
     accum[1] >>= ConvolutionFilter1D::kShiftBits;
     accum[2] >>= ConvolutionFilter1D::kShiftBits;
     if (has_alpha)
       accum[3] >>= ConvolutionFilter1D::kShiftBits;
 
     // Store the new pixel.
-    out_row[byte_offset + 0] = ClampTo8(accum[0]);
-    out_row[byte_offset + 1] = ClampTo8(accum[1]);
-    out_row[byte_offset + 2] = ClampTo8(accum[2]);
+    out_row[byte_offset + R_OFFSET_IDX] = ClampTo8(accum[0]);
+    out_row[byte_offset + G_OFFSET_IDX] = ClampTo8(accum[1]);
+    out_row[byte_offset + B_OFFSET_IDX] = ClampTo8(accum[2]);
     if (has_alpha) {
       unsigned char alpha = ClampTo8(accum[3]);
 
       // Make sure the alpha channel doesn't come out smaller than any of the
       // color channels. We use premultipled alpha channels, so this should
       // never happen, but rounding errors will cause this from time to time.
       // These "impossible" colors will cause overflows (and hence random pixel
       // values) when the resulting bitmap is drawn to the screen.
       //
       // We only need to do this when generating the final output row (here).
-      int max_color_channel = NS_MAX(out_row[byte_offset + 0],
-          NS_MAX(out_row[byte_offset + 1], out_row[byte_offset + 2]));
+      int max_color_channel = NS_MAX(out_row[byte_offset + R_OFFSET_IDX],
+          NS_MAX(out_row[byte_offset + G_OFFSET_IDX], out_row[byte_offset + B_OFFSET_IDX]));
       if (alpha < max_color_channel)
-        out_row[byte_offset + 3] = max_color_channel;
+        out_row[byte_offset + A_OFFSET_IDX] = max_color_channel;
       else
-        out_row[byte_offset + 3] = alpha;
+        out_row[byte_offset + A_OFFSET_IDX] = alpha;
     } else {
       // No alpha channel, the image is opaque.
-      out_row[byte_offset + 3] = 0xff;
+      out_row[byte_offset + A_OFFSET_IDX] = 0xff;
     }
   }
 }
 
 
 // Convolves horizontally along a single row. The row data is given in
 // |src_data| and continues for the num_values() of the filter.
 void ConvolveHorizontally_SSE2(const unsigned char* src_data,
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -137,16 +137,17 @@ EXPORTS_mozilla/layers =\
         ImageContainerParent.h \
         ShadowLayers.h \
         ShadowLayersChild.h \
         ShadowLayersParent.h \
         ShadowLayersManager.h \
         RenderTrace.h \
         SharedImageUtils.h \
         ShmemYCbCrImage.h \
+        TaskThrottler.h \
         $(NULL)
 
 CPPSRCS += \
         AsyncPanZoomController.cpp \
         Axis.cpp \
         CompositorCocoaWidgetHelper.cpp \
         CompositorChild.cpp \
         CompositorParent.cpp \
@@ -156,16 +157,17 @@ CPPSRCS += \
         ImageContainerChild.cpp \
         ImageContainerParent.cpp \
         ShadowLayers.cpp \
         ShadowLayerChild.cpp \
         ShadowLayersChild.cpp \
         ShadowLayerParent.cpp \
         ShadowLayersParent.cpp \
         ShmemYCbCrImage.cpp \
+        TaskThrottler.cpp \
         $(NULL)
 
 ifdef MOZ_X11 #{
 EXPORTS_mozilla/layers += ShadowLayerUtilsX11.h
 CPPSRCS += ShadowLayerUtilsX11.cpp
 endif #}
 
 ifdef MOZ_ENABLE_D3D10_LAYER
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -962,17 +962,21 @@ void AsyncPanZoomController::RequestCont
             float(MIN_ZOOM) / 2.0f, float(MAX_ZOOM));
   // Scale down the resolution a bit based on acceleration.
   mFrameMetrics.mZoom.width = mFrameMetrics.mZoom.height =
                               actualZoom / accelerationFactor;
 
   // This message is compressed, so fire whether or not we already have a paint
   // queued up. We need to know whether or not a paint was requested anyways,
   // for the purposes of content calling window.scrollTo().
-  mGeckoContentController->RequestContentRepaint(mFrameMetrics);
+  mPaintThrottler.PostTask(
+    FROM_HERE,
+    NewRunnableMethod(mGeckoContentController.get(),
+                      &GeckoContentController::RequestContentRepaint,
+                      mFrameMetrics));
   mLastPaintRequestMetrics = mFrameMetrics;
   mWaitingForContentToPaint = true;
 
   // Set the zoom back to what it was for the purpose of logic control.
   mFrameMetrics.mZoom = gfxSize(actualZoom, actualZoom);
 }
 
 bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
@@ -1076,16 +1080,18 @@ bool AsyncPanZoomController::SampleConte
   mLastSampleTime = aSampleTime;
 
   return requestAnimationFrame;
 }
 
 void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFrame, bool aIsFirstPaint) {
   MonitorAutoLock monitor(mMonitor);
 
+  mPaintThrottler.TaskComplete();
+
   mLastContentPaintMetrics = aViewportFrame;
 
   if (mWaitingForContentToPaint) {
     // Remove the oldest sample we have if adding a new sample takes us over our
     // desired number of samples.
     if (mPreviousPaintDurations.Length() >= NUM_PAINT_DURATION_SAMPLES) {
       mPreviousPaintDurations.RemoveElementAt(0);
     }
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -10,16 +10,17 @@
 #include "GeckoContentController.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "InputData.h"
 #include "Axis.h"
 #include "nsContentUtils.h"
+#include "TaskThrottler.h"
 
 #include "base/message_loop.h"
 
 namespace mozilla {
 namespace layers {
 
 class CompositorParent;
 class GestureEventListener;
@@ -453,16 +454,17 @@ private:
   /**
    * Helper to set the current state. Holds the monitor before actually setting
    * it. If the monitor is already held by the current thread, it is safe to
    * instead use: |mState = NEWSTATE;|
    */
   void SetState(PanZoomState aState);
 
   nsRefPtr<CompositorParent> mCompositorParent;
+  TaskThrottler mPaintThrottler;
   nsRefPtr<GeckoContentController> mGeckoContentController;
   nsRefPtr<GestureEventListener> mGestureEventListener;
 
   // Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the
   // monitor. Do not read from or modify either of them without locking.
   FrameMetrics mFrameMetrics;
   // These are the metrics at last content paint, the most recent
   // values we were notified of in NotifyLayersUpdate().
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -34,22 +34,26 @@ typedef std::vector<Edit> EditVector;
 typedef std::set<ShadowableLayer*> ShadowableLayerSet;
 
 class Transaction
 {
 public:
   Transaction()
     : mSwapRequired(false)
     , mOpen(false)
+    , mRotationChanged(false)
   {}
 
   void Begin(const nsIntRect& aTargetBounds, ScreenRotation aRotation)
   {
     mOpen = true;
     mTargetBounds = aTargetBounds;
+    if (aRotation != mTargetRotation) {
+        mRotationChanged = true;
+    }
     mTargetRotation = aRotation;
   }
 
   void AddEdit(const Edit& aEdit)
   {
     NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
     mCset.push_back(aEdit);
   }
@@ -81,33 +85,38 @@ public:
   void End()
   {
     mCset.clear();
     mPaints.clear();
     mDyingBuffers.Clear();
     mMutants.clear();
     mOpen = false;
     mSwapRequired = false;
+    mRotationChanged = false;
   }
 
   bool Empty() const {
     return mCset.empty() && mPaints.empty() && mMutants.empty();
   }
+  bool RotationChanged() const {
+    return mRotationChanged;
+  }
   bool Finished() const { return !mOpen && Empty(); }
 
   EditVector mCset;
   EditVector mPaints;
   BufferArray mDyingBuffers;
   ShadowableLayerSet mMutants;
   nsIntRect mTargetBounds;
   ScreenRotation mTargetRotation;
   bool mSwapRequired;
 
 private:
   bool mOpen;
+  bool mRotationChanged;
 
   // disabled
   Transaction(const Transaction&);
   Transaction& operator=(const Transaction&);
 };
 struct AutoTxnEnd {
   AutoTxnEnd(Transaction* aTxn) : mTxn(aTxn) {}
   ~AutoTxnEnd() { mTxn->End(); }
@@ -280,18 +289,18 @@ ShadowLayerForwarder::EndTransaction(Inf
 {
   SAMPLE_LABEL("ShadowLayerForwarder", "EndTranscation");
   RenderTraceScope rendertrace("Foward Transaction", "000091");
   NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to");
   NS_ABORT_IF_FALSE(!mTxn->Finished(), "forgot BeginTransaction?");
 
   AutoTxnEnd _(mTxn);
 
-  if (mTxn->Empty()) {
-    MOZ_LAYERS_LOG(("[LayersForwarder] 0-length cset (?), skipping Update()"));
+  if (mTxn->Empty() && !mTxn->RotationChanged()) {
+    MOZ_LAYERS_LOG(("[LayersForwarder] 0-length cset (?) and no rotation event, skipping Update()"));
     return true;
   }
 
   MOZ_LAYERS_LOG(("[LayersForwarder] destroying buffers..."));
 
   for (uint32_t i = 0; i < mTxn->mDyingBuffers.Length(); ++i) {
     DestroySharedSurface(&mTxn->mDyingBuffers[i]);
   }
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/TaskThrottler.cpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
+/* vim: set sw=2 sts=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "base/basictypes.h"
+#include "base/message_loop.h"
+#include "TaskThrottler.h"
+
+namespace mozilla {
+namespace layers {
+
+TaskThrottler::TaskThrottler()
+  : mOutstanding(false)
+  , mQueuedTask(nullptr)
+{ }
+
+void
+TaskThrottler::PostTask(const tracked_objects::Location& aLocation,
+                        CancelableTask* aTask)
+{
+  aTask->SetBirthPlace(aLocation);
+
+  if (mOutstanding) {
+    if (mQueuedTask) {
+      mQueuedTask->Cancel();
+    }
+    mQueuedTask = aTask;
+  } else {
+    aTask->Run();
+    delete aTask;
+    mOutstanding = true;
+  }
+}
+
+void
+TaskThrottler::TaskComplete()
+{
+  if (mQueuedTask) {
+    mQueuedTask->Run();
+    mQueuedTask = nullptr;
+  } else {
+    mOutstanding = false;
+  }
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/TaskThrottler.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_TaskThrottler_h
+#define mozilla_dom_TaskThrottler_h
+
+#include "nsAutoPtr.h"
+
+class CancelableTask;
+namespace tracked_objects {
+  class Location;
+}
+
+namespace mozilla {
+namespace layers {
+
+/** The TaskThrottler prevents update event overruns. It is used in cases where
+ * you're sending an async message and waiting for a reply. You need to call
+ * PostTask to queue a task and TaskComplete when you get a response.
+ *
+ * The call to TaskComplete will run the recent task posted since the last
+ * request was sent, if any. This means that at any time there can be at most 1
+ * outstanding request being processed and at most 1 queued behind it.
+ *
+ * This is used in the context of repainting a scrollable region. While another
+ * process is painting you might get several updates from the UI thread but when
+ * the paint is complete you want to send the most recent.
+ */
+
+class TaskThrottler {
+public:
+  TaskThrottler();
+
+  /** Post a task to be run as soon as there are no outstanding tasks.
+   *
+   * @param aLocation Use the macro FROM_HERE
+   * @param aTask     Ownership of this object is transferred to TaskThrottler
+   *                  which will delete it when it is either run or becomes
+   *                  obsolete or the TaskThrottler is destructed.
+   */
+  void PostTask(const tracked_objects::Location& aLocation,
+                CancelableTask* aTask);
+  void TaskComplete();
+
+private:
+  bool mOutstanding;
+  nsAutoPtr<CancelableTask> mQueuedTask;
+};
+
+}
+}
+
+#endif // mozilla_dom_TaskThrottler_h
--- a/gfx/skia/include/core/SkPreConfig.h
+++ b/gfx/skia/include/core/SkPreConfig.h
@@ -89,17 +89,17 @@
 
 #if !defined(SK_SCALAR_IS_FLOAT) && !defined(SK_SCALAR_IS_FIXED)
     #define SK_SCALAR_IS_FLOAT
 #endif
 
 //////////////////////////////////////////////////////////////////////
 
 #if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN)
-    #if defined (__ppc__) || defined(__ppc64__)
+#if defined (__ppc__) || defined(__PPC__) || defined(__ppc64__) || defined(__PPC64__)
         #define SK_CPU_BENDIAN
     #else
         #define SK_CPU_LENDIAN
     #endif
 #endif
 
 //////////////////////////////////////////////////////////////////////
 
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -191,16 +191,17 @@ FT2FontEntry::CreateFontEntry(const gfxP
     // as it's not guaranteed that the face has valid names (bug 737315)
     FT2FontEntry* fe =
         FT2FontEntry::CreateFontEntry(face, nullptr, 0, aProxyEntry.Name(),
                                       aFontData);
     if (fe) {
         fe->mItalic = aProxyEntry.mItalic;
         fe->mWeight = aProxyEntry.mWeight;
         fe->mStretch = aProxyEntry.mStretch;
+        fe->mIsUserFont = true;
     }
     return fe;
 }
 
 class FTUserFontData {
 public:
     FTUserFontData(FT_Face aFace, const uint8_t* aData)
         : mFace(aFace), mFontData(aData)
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -77,18 +77,24 @@ gfxCharacterMap::NotifyReleased()
 {
     gfxPlatformFontList *fontlist = gfxPlatformFontList::PlatformFontList();
     if (mShared) {
         fontlist->RemoveCmap(this);
     }
     delete this;
 }
 
-gfxFontEntry::~gfxFontEntry() 
-{
+gfxFontEntry::~gfxFontEntry()
+{
+    // For downloaded fonts, we need to tell the user font cache that this
+    // entry is being deleted.
+    if (!mIsProxy && IsUserFont() && !IsLocalUserFont()) {
+        gfxUserFontSet::UserFontCache::ForgetFont(this);
+    }
+
     if (mSVGGlyphs) {
         delete mSVGGlyphs;
     }
     delete mUserFontData;
 }
 
 bool gfxFontEntry::IsSymbolFont() 
 {
@@ -1233,16 +1239,21 @@ gfxFontCache::gfxFontCache()
                                  SHAPED_WORD_TIMEOUT_SECONDS * 1000,
                                  nsITimer::TYPE_REPEATING_SLACK);
     }
 #endif
 }
 
 gfxFontCache::~gfxFontCache()
 {
+    // Ensure the user font cache releases its references to font entries,
+    // so they aren't kept alive after the font instances and font-list
+    // have been shut down.
+    gfxUserFontSet::UserFontCache::Shutdown();
+
     if (mWordCacheExpirationTimer) {
         mWordCacheExpirationTimer->Cancel();
         mWordCacheExpirationTimer = nullptr;
     }
 
     // Expire everything that has a zero refcount, so we don't leak them.
     AgeAllGenerations();
     // All fonts should be gone.
--- a/gfx/thebes/gfxPangoFonts.cpp
+++ b/gfx/thebes/gfxPangoFonts.cpp
@@ -1499,16 +1499,25 @@ gfxFcFontSet::SortPreferredFonts(bool &a
                 continue;
 
             entry->mKey = family; // initialize new entry
         }
 
         for (uint32_t f = 0; f < familyFonts->Length(); ++f) {
             FcPattern *font = familyFonts->ElementAt(f);
 
+            // Fix up the family name of user-font patterns, as the same
+            // font entry may be used (via the UserFontCache) for multiple
+            // CSS family names
+            if (isUserFont) {
+                font = FcPatternDuplicate(font);
+                FcPatternDel(font, FC_FAMILY);
+                FcPatternAddString(font, FC_FAMILY, family);
+            }
+
             // User fonts are already filtered by slant (but not size) in
             // mUserFontSet->FindFontEntry().
             if (!isUserFont && !SlantIsAcceptable(font, requestedSlant))
                 continue;
             if (requestedSize != -1.0 && !SizeIsAcceptable(font, requestedSize))
                 continue;
 
             for (uint32_t r = 0; r < requiredLangs.Length(); ++r) {
@@ -1519,17 +1528,22 @@ gfxFcFontSet::SortPreferredFonts(bool &a
                     requiredLangs.RemoveElementAt(r);
                     --r;
                 }
             }
 
             // FcFontSetDestroy will remove a reference but FcFontSetAdd
             // does _not_ take a reference!
             if (FcFontSetAdd(fontSet, font)) {
-                FcPatternReference(font);
+                // We don't add a reference here for user fonts, because we're
+                // using a local clone of the pattern (see above) in order to
+                // override the family name
+                if (!isUserFont) {
+                    FcPatternReference(font);
+                }
             }
         }
     }
 
     FcPattern *truncateMarker = NULL;
     for (uint32_t r = 0; r < requiredLangs.Length(); ++r) {
         const nsTArray< nsCountedRef<FcPattern> >& langFonts =
             utils->GetFontsForLang(requiredLangs[r].mLang);
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -10,16 +10,18 @@
 
 #include "gfxUserFontSet.h"
 #include "gfxPlatform.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "prlong.h"
 #include "nsNetUtil.h"
 #include "nsIProtocolHandler.h"
+#include "nsIPrincipal.h"
+#include "mozilla/Telemetry.h"
 
 #include "woff.h"
 
 #include "opentype-sanitiser.h"
 #include "ots-memory-stream.h"
 
 using namespace mozilla;
 
@@ -401,16 +403,17 @@ StoreUserFontData(gfxFontEntry* aFontEnt
     }
     gfxUserFontData* userFontData = aFontEntry->mUserFontData;
     userFontData->mSrcIndex = aProxy->mSrcIndex;
     const gfxFontFaceSrc& src = aProxy->mSrcList[aProxy->mSrcIndex];
     if (src.mIsLocal) {
         userFontData->mLocalName = src.mLocalName;
     } else {
         userFontData->mURI = src.mURI;
+        userFontData->mPrincipal = aProxy->mPrincipal;
     }
     userFontData->mFormat = src.mFormatFlags;
     userFontData->mRealName = aOriginalName;
     if (aMetadata) {
         userFontData->mMetadata.SwapElements(*aMetadata);
         userFontData->mMetaOrigLen = aMetaOrigLen;
     }
 }
@@ -554,58 +557,75 @@ gfxUserFontSet::LoadNext(gfxProxyFontEnt
             }
         }
 
         // src url ==> start the load process
         else {
             if (gfxPlatform::GetPlatform()->IsFontFormatSupported(currSrc.mURI,
                     currSrc.mFormatFlags)) {
 
-                nsresult rv;
-                bool loadDoesntSpin = false;
-                rv = NS_URIChainHasFlags(currSrc.mURI,
-                       nsIProtocolHandler::URI_SYNC_LOAD_IS_OK,
-                       &loadDoesntSpin);
-
-                if (NS_SUCCEEDED(rv) && loadDoesntSpin) {
-                    uint8_t *buffer = nullptr;
-                    uint32_t bufferLength = 0;
+                nsIPrincipal *principal = nullptr;
+                nsresult rv = CheckFontLoad(&currSrc, &principal);
 
-                    // sync load font immediately
-                    rv = SyncLoadFontData(aProxyEntry, &currSrc, buffer,
-                                          bufferLength);
-
-                    if (NS_SUCCEEDED(rv) &&
-                        LoadFont(aProxyEntry, buffer, bufferLength)) {
+                if (NS_SUCCEEDED(rv) && principal != nullptr) {
+                    // see if we have an existing entry for this source
+                    gfxFontEntry *fe =
+                        UserFontCache::GetFont(currSrc.mURI, principal,
+                                               aProxyEntry);
+                    if (fe) {
+                        ReplaceFontEntry(aProxyEntry, fe);
                         return STATUS_LOADED;
-                    } else {
-                        LogMessage(aProxyEntry, "font load failed",
-                                   nsIScriptError::errorFlag, rv);
                     }
 
-                } else {
-                    // otherwise load font async
-                    rv = StartLoad(aProxyEntry, &currSrc);
-                    bool loadOK = NS_SUCCEEDED(rv);
+                    // record the principal returned by CheckFontLoad,
+                    // for use when creating a channel
+                    // and when caching the loaded entry
+                    aProxyEntry->mPrincipal = principal;
+
+                    bool loadDoesntSpin = false;
+                    rv = NS_URIChainHasFlags(currSrc.mURI,
+                           nsIProtocolHandler::URI_SYNC_LOAD_IS_OK,
+                           &loadDoesntSpin);
+                    if (NS_SUCCEEDED(rv) && loadDoesntSpin) {
+                        uint8_t *buffer = nullptr;
+                        uint32_t bufferLength = 0;
 
-                    if (loadOK) {
+                        // sync load font immediately
+                        rv = SyncLoadFontData(aProxyEntry, &currSrc,
+                                              buffer, bufferLength);
+                        if (NS_SUCCEEDED(rv) &&
+                            (fe = LoadFont(aProxyEntry, buffer, bufferLength))) {
+                            UserFontCache::CacheFont(fe);
+                            return STATUS_LOADED;
+                        } else {
+                            LogMessage(aProxyEntry, "font load failed",
+                                       nsIScriptError::errorFlag, rv);
+                        }
+                    } else {
+                        // otherwise load font async
+                        rv = StartLoad(aProxyEntry, &currSrc);
+                        if (NS_SUCCEEDED(rv)) {
 #ifdef PR_LOGGING
-                        if (LOG_ENABLED()) {
-                            nsAutoCString fontURI;
-                            currSrc.mURI->GetSpec(fontURI);
-                            LOG(("userfonts (%p) [src %d] loading uri: (%s) for (%s)\n",
-                                 this, aProxyEntry->mSrcIndex, fontURI.get(),
-                                 NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
+                            if (LOG_ENABLED()) {
+                                nsAutoCString fontURI;
+                                currSrc.mURI->GetSpec(fontURI);
+                                LOG(("userfonts (%p) [src %d] loading uri: (%s) for (%s)\n",
+                                     this, aProxyEntry->mSrcIndex, fontURI.get(),
+                                     NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
+                            }
+#endif
+                            return STATUS_LOADING;
+                        } else {
+                            LogMessage(aProxyEntry, "download failed",
+                                       nsIScriptError::errorFlag, rv);
                         }
-#endif
-                        return STATUS_LOADING;
-                    } else {
-                        LogMessage(aProxyEntry, "download failed",
-                                   nsIScriptError::errorFlag, rv);
                     }
+                } else {
+                    LogMessage(aProxyEntry, "download not allowed",
+                               nsIScriptError::errorFlag, rv);
                 }
             } else {
                 // We don't log a warning to the web console yet,
                 // as another source may load successfully
                 aProxyEntry->mUnsupportedFormat = true;
             }
         }
 
@@ -747,16 +767,17 @@ gfxUserFontSet::LoadFont(gfxProxyFontEnt
             nsAutoCString fontURI;
             aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI);
             LOG(("userfonts (%p) [src %d] loaded uri: (%s) for (%s) gen: %8.8x\n",
                  this, aProxy->mSrcIndex, fontURI.get(),
                  NS_ConvertUTF16toUTF8(aProxy->mFamily->Name()).get(),
                  uint32_t(mGeneration)));
         }
 #endif
+        UserFontCache::CacheFont(fe);
         ReplaceFontEntry(aProxy, fe);
     } else {
 #ifdef PR_LOGGING
         if (LOG_ENABLED()) {
             nsAutoCString fontURI;
             aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI);
             LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s)"
                  " error making platform font\n",
@@ -773,8 +794,99 @@ gfxMixedFontFamily*
 gfxUserFontSet::GetFamily(const nsAString& aFamilyName) const
 {
     nsAutoString key(aFamilyName);
     ToLowerCase(key);
 
     return mFontFamilies.GetWeak(key);
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// gfxUserFontSet::UserFontCache - re-use platform font entries for user fonts
+// across pages/fontsets rather than instantiating new platform fonts.
+//
+// Entries are added to this cache when a platform font is instantiated from
+// downloaded data, and removed when the platform font entry is destroyed.
+// We don't need to use a timed expiration scheme here because the gfxFontEntry
+// for a downloaded font will be kept alive by its corresponding gfxFont
+// instance(s) until they are deleted, and *that* happens using an expiration
+// tracker (gfxFontCache). The result is that the downloaded font instances
+// recorded here will persist between pages and can get reused (provided the
+// source URI and principal match, of course).
+///////////////////////////////////////////////////////////////////////////////
+
+nsTHashtable<gfxUserFontSet::UserFontCache::Entry>*
+    gfxUserFontSet::UserFontCache::sUserFonts = nullptr;
+
+bool
+gfxUserFontSet::UserFontCache::Entry::KeyEquals(const KeyTypePointer aKey) const
+{
+    bool equal;
+    if (NS_FAILED(mURI->Equals(aKey->mURI, &equal)) || !equal) {
+        return false;
+    }
+
+    if (NS_FAILED(mPrincipal->Equals(aKey->mPrincipal, &equal)) || !equal) {
+        return false;
+    }
+
+    const gfxFontEntry *fe = aKey->mFontEntry;
+    if (mFontEntry->mItalic           != fe->mItalic          ||
+        mFontEntry->mWeight           != fe->mWeight          ||
+        mFontEntry->mStretch          != fe->mStretch         ||
+        mFontEntry->mFeatureSettings  != fe->mFeatureSettings ||
+        mFontEntry->mLanguageOverride != fe->mLanguageOverride) {
+        return false;
+    }
+
+    return true;
+}
+
+void
+gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry *aFontEntry)
+{
+    if (!sUserFonts) {
+        sUserFonts = new nsTHashtable<Entry>;
+        sUserFonts->Init();
+    }
+
+    gfxUserFontData *data = aFontEntry->mUserFontData;
+    sUserFonts->PutEntry(Key(data->mURI, data->mPrincipal, aFontEntry));
+}
+
+void
+gfxUserFontSet::UserFontCache::ForgetFont(gfxFontEntry *aFontEntry)
+{
+    if (!sUserFonts) {
+        // if we've already deleted the cache (i.e. during shutdown),
+        // just ignore this
+        return;
+    }
+
+    gfxUserFontData *data = aFontEntry->mUserFontData;
+    sUserFonts->RemoveEntry(Key(data->mURI, data->mPrincipal, aFontEntry));
+}
+
+gfxFontEntry*
+gfxUserFontSet::UserFontCache::GetFont(nsIURI            *aSrcURI,
+                                       nsIPrincipal      *aPrincipal,
+                                       gfxProxyFontEntry *aProxy)
+{
+    if (!sUserFonts) {
+        return nullptr;
+    }
+
+    Entry* entry = sUserFonts->GetEntry(Key(aSrcURI, aPrincipal, aProxy));
+    if (entry) {
+        return entry->GetFontEntry();
+    }
+
+    return nullptr;
+}
+
+void
+gfxUserFontSet::UserFontCache::Shutdown()
+{
+    if (sUserFonts) {
+        delete sUserFonts;
+        sUserFonts = nullptr;
+    }
+}
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -9,20 +9,21 @@
 #include "gfxTypes.h"
 #include "gfxFont.h"
 #include "gfxFontUtils.h"
 #include "nsRefPtrHashtable.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsIURI.h"
 #include "nsIFile.h"
+#include "nsIPrincipal.h"
 #include "nsISupportsImpl.h"
 #include "nsIScriptError.h"
+#include "nsURIHashKey.h"
 
-class nsIURI;
 class gfxMixedFontFamily;
 class nsFontFaceLoader;
 
 // parsed CSS @font-face rule information
 // lifetime: from when @font-face rule processed until font is loaded
 struct gfxFontFaceSrc {
     bool                   mIsLocal;       // url or local
 
@@ -30,20 +31,19 @@ struct gfxFontFaceSrc {
     bool                   mUseOriginPrincipal;
 
     // format hint flags, union of all possible formats
     // (e.g. TrueType, EOT, SVG, etc.)
     // see FLAG_FORMAT_* enum values below
     uint32_t               mFormatFlags;
 
     nsString               mLocalName;     // full font name if local
-    nsCOMPtr<nsIURI>       mURI;           // uri if url 
+    nsCOMPtr<nsIURI>       mURI;           // uri if url
     nsCOMPtr<nsIURI>       mReferrer;      // referrer url if url
-    nsCOMPtr<nsISupports>  mOriginPrincipal; // principal if url 
-    
+    nsCOMPtr<nsIPrincipal> mOriginPrincipal; // principal if url
 };
 
 // Subclassed to store platform-specific code cleaned out when font entry is
 // deleted.
 // Lifetime: from when platform font is created until it is deactivated.
 // If the platform does not need to add any platform-specific code/data here,
 // then the gfxUserFontSet will allocate a base gfxUserFontData and attach
 // to the entry to track the basic user font info fields here.
@@ -51,16 +51,17 @@ class gfxUserFontData {
 public:
     gfxUserFontData()
         : mSrcIndex(0), mFormat(0), mMetaOrigLen(0)
     { }
     virtual ~gfxUserFontData() { }
 
     nsTArray<uint8_t> mMetadata;  // woff metadata block (compressed), if any
     nsCOMPtr<nsIURI>  mURI;       // URI of the source, if it was url()
+    nsCOMPtr<nsIPrincipal> mPrincipal; // principal for the download, if url()
     nsString          mLocalName; // font name used for the source, if local()
     nsString          mRealName;  // original fullname from the font resource
     uint32_t          mSrcIndex;  // index in the rule's source list
     uint32_t          mFormat;    // format hint for the source used, if any
     uint32_t          mMetaOrigLen; // length needed to decompress metadata
 };
 
 // initially contains a set of proxy font entry objects, replaced with
@@ -197,20 +198,24 @@ public:
     }
 
     // lookup a font entry for a given style, returns null if not loaded
     gfxFontEntry *FindFontEntry(const nsAString& aName,
                                 const gfxFontStyle& aFontStyle,
                                 bool& aFoundFamily,
                                 bool& aNeedsBold,
                                 bool& aWaitForUserFont);
-                                
+
+    // check whether the given source is allowed to be loaded
+    virtual nsresult CheckFontLoad(const gfxFontFaceSrc *aFontFaceSrc,
+                                   nsIPrincipal **aPrincipal) = 0;
+
     // initialize the process that loads external font data, which upon 
     // completion will call OnLoadComplete method
-    virtual nsresult StartLoad(gfxProxyFontEntry *aProxy, 
+    virtual nsresult StartLoad(gfxProxyFontEntry *aProxy,
                                const gfxFontFaceSrc *aFontFaceSrc) = 0;
 
     // when download has been completed, pass back data here
     // aDownloadStatus == NS_OK ==> download succeeded, error otherwise
     // returns true if platform font creation sucessful (or local()
     // reference was next in line)
     // Ownership of aFontData is passed in here; the font set must
     // ensure that it is eventually deleted with NS_Free().
@@ -226,37 +231,131 @@ public:
 
     // generation - each time a face is loaded, generation is
     // incremented so that the change can be recognized 
     uint64_t GetGeneration() { return mGeneration; }
 
     // increment the generation on font load
     void IncrementGeneration();
 
+    class UserFontCache {
+    public:
+        // Record a loaded user-font in the cache. This requires that the
+        // font-entry's userFontData has been set up already, as it relies
+        // on the URI and Principal recorded there.
+        static void CacheFont(gfxFontEntry *aFontEntry);
+
+        // The given gfxFontEntry is being destroyed, so remove any record that
+        // refers to it.
+        static void ForgetFont(gfxFontEntry *aFontEntry);
+
+        // Return the gfxFontEntry corresponding to a given URI and principal,
+        // and the features of the given proxy, or nullptr if none is available
+        static gfxFontEntry* GetFont(nsIURI            *aSrcURI,
+                                     nsIPrincipal      *aPrincipal,
+                                     gfxProxyFontEntry *aProxy);
+
+        // Clear everything so that we don't leak URIs and Principals.
+        static void Shutdown();
+
+    private:
+        // Key used to look up entries in the user-font cache.
+        // Note that key comparison does *not* use the mFontEntry field
+        // as a whole; it only compares specific fields within the entry
+        // (weight/width/style/features) that could affect font selection
+        // or rendering, and that must match between a font-set's proxy
+        // entry and the corresponding "real" font entry.
+        struct Key {
+            nsCOMPtr<nsIURI>        mURI;
+            nsCOMPtr<nsIPrincipal>  mPrincipal;
+            gfxFontEntry           *mFontEntry;
+
+            Key(nsIURI* aURI, nsIPrincipal* aPrincipal,
+                gfxFontEntry* aFontEntry)
+                : mURI(aURI),
+                  mPrincipal(aPrincipal),
+                  mFontEntry(aFontEntry)
+            { }
+        };
+
+        class Entry : public PLDHashEntryHdr {
+        public:
+            typedef const Key& KeyType;
+            typedef const Key* KeyTypePointer;
+
+            Entry(KeyTypePointer aKey)
+                : mURI(aKey->mURI),
+                  mPrincipal(aKey->mPrincipal),
+                  mFontEntry(aKey->mFontEntry)
+            { }
+
+            Entry(const Entry& aOther)
+                : mURI(aOther.mURI),
+                  mPrincipal(aOther.mPrincipal),
+                  mFontEntry(aOther.mFontEntry)
+            { }
+
+            ~Entry() { }
+
+            bool KeyEquals(const KeyTypePointer aKey) const;
+
+            static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+
+            static PLDHashNumber HashKey(const KeyTypePointer aKey) {
+                uint32_t principalHash;
+                aKey->mPrincipal->GetHashValue(&principalHash);
+                return mozilla::HashGeneric(principalHash,
+                                            nsURIHashKey::HashKey(aKey->mURI),
+                                            HashFeatures(aKey->mFontEntry->mFeatureSettings),
+                                            ( aKey->mFontEntry->mItalic |
+                                             (aKey->mFontEntry->mWeight << 1) |
+                                             (aKey->mFontEntry->mStretch << 10) ) ^
+                                             aKey->mFontEntry->mLanguageOverride);
+            }
+
+            enum { ALLOW_MEMMOVE = false };
+
+            gfxFontEntry* GetFontEntry() const { return mFontEntry; }
+
+        private:
+            static uint32_t
+            HashFeatures(const nsTArray<gfxFontFeature>& aFeatures) {
+                return mozilla::HashBytes(aFeatures.Elements(),
+                                          aFeatures.Length() * sizeof(gfxFontFeature));
+            }
+
+            nsCOMPtr<nsIURI>       mURI;
+            nsCOMPtr<nsIPrincipal> mPrincipal;
+
+            // The "real" font entry corresponding to this downloaded font.
+            // The font entry MUST notify the cache when it is destroyed
+            // (by calling Forget()).
+            gfxFontEntry          *mFontEntry;
+        };
+
+        static nsTHashtable<Entry> *sUserFonts;
+    };
+
 protected:
     // for a given proxy font entry, attempt to load the next resource
     // in the src list
     LoadStatus LoadNext(gfxProxyFontEntry *aProxyEntry);
 
     // helper method for creating a platform font
     // returns font entry if platform font creation successful
     // Ownership of aFontData is passed in here; the font set must
     // ensure that it is eventually deleted with NS_Free().
     gfxFontEntry* LoadFont(gfxProxyFontEntry *aProxy,
                            const uint8_t *aFontData, uint32_t &aLength);
 
     // parse data for a data URL
     virtual nsresult SyncLoadFontData(gfxProxyFontEntry *aFontToLoad,
                                       const gfxFontFaceSrc *aFontFaceSrc,
                                       uint8_t* &aBuffer,
-                                      uint32_t &aBufferLength)
-    {
-        // implemented in nsUserFontSet
-        return NS_ERROR_NOT_IMPLEMENTED;
-    }
+                                      uint32_t &aBufferLength) = 0;
 
     gfxMixedFontFamily *GetFamily(const nsAString& aName) const;
 
     // report a problem of some kind (implemented in nsUserFontSet)
     virtual nsresult LogMessage(gfxProxyFontEntry *aProxy,
                                 const char *aMessage,
                                 uint32_t aFlags = nsIScriptError::errorFlag,
                                 nsresult aStatus = NS_OK) = 0;
@@ -315,12 +414,13 @@ public:
         LOADING_FAILED       // failed to load any source: use fallback
     };
     LoadingState             mLoadingState;
     bool                     mUnsupportedFormat;
 
     nsTArray<gfxFontFaceSrc> mSrcList;
     uint32_t                 mSrcIndex; // index of loading src item
     nsFontFaceLoader        *mLoader; // current loader for this entry, if any
+    nsCOMPtr<nsIPrincipal>   mPrincipal;
 };
 
 
 #endif /* GFX_USER_FONT_SET_H */
--- a/image/src/Decoder.h
+++ b/image/src/Decoder.h
@@ -84,35 +84,35 @@ public:
 
   /*
    * State.
    */
 
   // If we're doing a "size decode", we more or less pass through the image
   // data, stopping only to scoop out the image dimensions. A size decode
   // must be enabled by SetSizeDecode() _before_calling Init().
-  bool IsSizeDecode() { return mSizeDecode; };
+  bool IsSizeDecode() { return mSizeDecode; }
   void SetSizeDecode(bool aSizeDecode)
   {
     NS_ABORT_IF_FALSE(!mInitialized, "Can't set size decode after Init()!");
     mSizeDecode = aSizeDecode;
   }
 
   // The number of frames we have, including anything in-progress. Thus, this
   // is only 0 if we haven't begun any frames.
   uint32_t GetFrameCount() { return mFrameCount; }
 
   // The number of complete frames we have (ie, not including anything in-progress).
   uint32_t GetCompleteFrameCount() { return mInFrame ? mFrameCount - 1 : mFrameCount; }
 
   // Error tracking
-  bool HasError() { return HasDataError() || HasDecoderError(); };
-  bool HasDataError() { return mDataError; };
-  bool HasDecoderError() { return NS_FAILED(mFailCode); };
-  nsresult GetDecoderError() { return mFailCode; };
+  bool HasError() { return HasDataError() || HasDecoderError(); }
+  bool HasDataError() { return mDataError; }
+  bool HasDecoderError() { return NS_FAILED(mFailCode); }
+  nsresult GetDecoderError() { return mFailCode; }
   void PostResizeError() { PostDataError(); }
   bool GetDecodeDone() const {
     return mDecodeDone;
   }
 
   // flags.  Keep these in sync with imgIContainer.idl.
   // SetDecodeFlags must be called before Init(), otherwise
   // default flags are assumed.
--- a/image/src/imgRequest.h
+++ b/image/src/imgRequest.h
@@ -109,17 +109,17 @@ public:
   }
 
   // Return the imgStatusTracker associated with this imgRequest. It may live
   // in |mStatusTracker| or in |mImage.mStatusTracker|, depending on whether
   // mImage has been instantiated yet.
   imgStatusTracker& GetStatusTracker();
 
   // Get the current principal of the image. No AddRefing.
-  inline nsIPrincipal* GetPrincipal() const { return mPrincipal.get(); };
+  inline nsIPrincipal* GetPrincipal() const { return mPrincipal.get(); }
 
   // Resize the cache entry to 0 if it exists
   void ResetCacheEntry();
 
   // Update the cache entry size based on the image container
   void UpdateCacheEntrySize();
 
   nsresult GetURI(nsIURI **aURI);
--- a/image/src/imgStatusTracker.h
+++ b/image/src/imgStatusTracker.h
@@ -109,17 +109,17 @@ public:
   // the request is finished downloading and decoding.  We only send
   // OnStopRequest and UnblockOnload, and only if necessary.
   void EmulateRequestFinished(imgRequestProxy* proxy, nsresult aStatus);
 
   // We manage a set of consumers that are using an image and thus concerned
   // with its status. Weak pointers.
   void AddConsumer(imgRequestProxy* aConsumer);
   bool RemoveConsumer(imgRequestProxy* aConsumer, nsresult aStatus);
-  size_t ConsumerCount() const { return mConsumers.Length(); };
+  size_t ConsumerCount() const { return mConsumers.Length(); }
 
   // This is intentionally non-general because its sole purpose is to support an
   // some obscure network priority logic in imgRequest. That stuff could probably
   // be improved, but it's too scary to mess with at the moment.
   bool FirstConsumerIs(imgRequestProxy* aConsumer) {
     return mConsumers.SafeElementAt(0, nullptr) == aConsumer;
   }
 
@@ -185,18 +185,18 @@ public:
   void SendUnblockOnload(imgRequestProxy* aProxy);
 
   void MaybeUnblockOnload();
 
   // Null out any reference to an associated image request
   void ClearRequest();
 
   // Weak pointer getters - no AddRefs.
-  inline mozilla::image::Image* GetImage() const { return mImage; };
-  inline imgRequest* GetRequest() const { return mRequest; };
+  inline mozilla::image::Image* GetImage() const { return mImage; }
+  inline imgRequest* GetRequest() const { return mRequest; }
 
   inline imgIDecoderObserver* GetDecoderObserver() { return mTrackerObserver.get(); }
 
 private:
   friend class imgStatusNotifyRunnable;
   friend class imgRequestNotifyRunnable;
   friend class imgStatusTrackerObserver;
 
--- a/intl/strres/src/nsStringBundle.cpp
+++ b/intl/strres/src/nsStringBundle.cpp
@@ -19,18 +19,16 @@
 #include "nsHashtable.h"
 #include "nsMemory.h"
 #include "plstr.h"
 #include "nsNetUtil.h"
 #include "nsIURL.h"
 #include "nsIComponentManager.h"
 #include "nsIMemory.h"
 #include "nsIObserverService.h"
-#include "pratom.h"
-#include "prmem.h"
 #include "nsCOMArray.h"
 #include "nsTextFormatter.h"
 #include "nsIErrorService.h"
 #include "nsICategoryManager.h"
 
 #include "nsPrintfCString.h"
 // for async loading
 #ifdef ASYNC_LOADING
--- a/js/src/assembler/assembler/AssemblerBufferWithConstantPool.h
+++ b/js/src/assembler/assembler/AssemblerBufferWithConstantPool.h
@@ -226,39 +226,16 @@ public:
         m_mask[m_numConsts] = static_cast<char>(isReusable ? ReusableConst : UniqueConst);
 
         AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, m_numConsts));
         ++m_numConsts;
 
         correctDeltas(4, 4);
     }
 
-    uint32_t *getPoolSpace(uint32_t insn, uint32_t constant, bool isReusable = false)
-    {
-        flushIfNoSpaceFor(4, 4);
-
-        m_loadOffsets.append(AssemblerBuffer::size());
-        if (isReusable)
-            for (int i = 0; i < m_numConsts; ++i) {
-                if (m_mask[i] == ReusableConst && m_pool[i] == constant) {
-                    AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, i));
-                    correctDeltas(4);
-                    return;
-                }
-            }
-
-        m_pool[m_numConsts] = constant;
-        m_mask[m_numConsts] = static_cast<char>(isReusable ? ReusableConst : UniqueConst);
-
-        AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, m_numConsts));
-        ++m_numConsts;
-
-        correctDeltas(4, 4);
-    }
-
     void putIntWithConstantDouble(uint32_t insn, double constant)
     {
         flushIfNoSpaceFor(4, 8);
 
         m_loadOffsets.append(AssemblerBuffer::size());
         bool isReusable = false;
 
         union DoublePun {
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -299,17 +299,17 @@ struct ClosureInfo
     , closure(NULL)
   {}
 
   ~ClosureInfo() {
     if (closure)
       ffi_closure_free(closure);
     if (errResult)
       js_free(errResult);
-  };
+  }
 };
 
 bool IsCTypesGlobal(JSObject* obj);
 
 JSCTypesCallbacks* GetCallbacks(JSObject* obj);
 
 JSBool InitTypeClasses(JSContext* cx, JSHandleObject parent);
 
--- a/js/src/ion/Bailouts.h
+++ b/js/src/ion/Bailouts.h
@@ -130,17 +130,17 @@ class BailoutClosure
 
   public:
     BailoutClosure()
       : bailoutPc_(NULL)
     { }
 
     void constructFrame() {
         guards_.construct();
-    };
+    }
     InvokeArgsGuard *argsGuard() {
         return &guards_.ref().iag;
     }
     BailoutFrameGuard *frameGuard() {
         return &guards_.ref().bfg;
     }
     StackFrame *entryfp() const {
         return entryfp_;
--- a/js/src/ion/BitSet.h
+++ b/js/src/ion/BitSet.h
@@ -21,17 +21,17 @@ class BitSet : private TempObject
   public:
     static size_t RawLengthForBits(size_t bits) {
         return 1 + bits / (8 * sizeof(uint32_t));
     }
 
   private:
     BitSet(unsigned int max) :
         max_(max),
-        bits_(NULL) {};
+        bits_(NULL) {}
 
     unsigned int max_;
     uint32_t *bits_;
 
     static inline uint32_t bitForValue(unsigned int value) {
         return 1l << (uint32_t)(value % (8 * sizeof(uint32_t)));
     }
 
--- a/js/src/ion/FixedList.h
+++ b/js/src/ion/FixedList.h
@@ -48,16 +48,16 @@ class FixedList
 
     T &operator[](size_t index) {
         JS_ASSERT(index < length_);
         return list_[index];
     }
     const T &operator [](size_t index) const {
         JS_ASSERT(index < length_);
         return list_[index];
-    };
+    }
 };
 
 } // namespace ion
 } // namespace js
 
 #endif // jsion_ion_fixed_list_h__
 
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -2,16 +2,17 @@
  * vim: set ts=4 sw=4 et tw=99:
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IonAnalysis.h"
 #include "IonBuilder.h"
+#include "Lowering.h"
 #include "MIRGraph.h"
 #include "Ion.h"
 #include "IonAnalysis.h"
 #include "IonSpewer.h"
 #include "frontend/BytecodeEmitter.h"
 
 #include "jsscriptinlines.h"
 #include "jstypedarrayinlines.h"
@@ -5238,26 +5239,31 @@ IonBuilder::jsop_getelem_dense()
     types::StackTypeSet *types = oracle->propertyRead(script_, pc);
     bool needsHoleCheck = !oracle->elementReadIsPacked(script_, pc);
     bool maybeUndefined = types->hasType(types::Type::UndefinedType());
 
     MDefinition *id = current->pop();
     MDefinition *obj = current->pop();
 
     JSValueType knownType = JSVAL_TYPE_UNKNOWN;
-    if (!needsHoleCheck && !barrier) {
+    if (!barrier) {
         knownType = types->getKnownTypeTag();
 
         // Null and undefined have no payload so they can't be specialized.
         // Since folding null/undefined while building SSA is not safe (see the
         // comment in IsPhiObservable), we just add an untyped load instruction
         // and rely on pushTypeBarrier and DCE to replace it with a null/undefined
         // constant.
         if (knownType == JSVAL_TYPE_UNDEFINED || knownType == JSVAL_TYPE_NULL)
             knownType = JSVAL_TYPE_UNKNOWN;
+
+        // Different architectures may want typed element reads which require
+        // hole checks to be done as either value or typed reads.
+        if (needsHoleCheck && !LIRGenerator::allowTypedElementHoleCheck())
+            knownType = JSVAL_TYPE_UNKNOWN;
     }
 
     // Ensure id is an integer.
     MInstruction *idInt32 = MToInt32::New(id);
     current->add(idInt32);
     id = idInt32;
 
     // Get the elements vector.
--- a/js/src/ion/LIR-Common.h
+++ b/js/src/ion/LIR-Common.h
@@ -29,27 +29,27 @@ class LBinaryMath : public LInstructionH
 
 // Used for jumps from other blocks. Also simplifies register allocation since
 // the first instruction of a block is guaranteed to have no uses.
 class LLabel : public LInstructionHelper<0, 0, 0>
 {
     Label label_;
 
   public:
-    LIR_HEADER(Label);
+    LIR_HEADER(Label)
 
     Label *label() {
         return &label_;
     }
 };
 
 class LNop : public LInstructionHelper<0, 0, 0>
 {
   public:
-    LIR_HEADER(Nop);
+    LIR_HEADER(Nop)
 };
 
 // An LOsiPoint captures a snapshot after a call and ensures enough space to
 // patch in a call to the invalidation mechanism.
 //
 // Note: LSafepoints are 1:1 with LOsiPoints, so it holds a reference to the
 // corresponding LSafepoint to inform it of the LOsiPoint's masm offset when it
 // gets CG'd.
@@ -64,17 +64,17 @@ class LOsiPoint : public LInstructionHel
         JS_ASSERT(safepoint && snapshot);
         assignSnapshot(snapshot);
     }
 
     LSafepoint *associatedSafepoint() {
         return safepoint_;
     }
 
-    LIR_HEADER(OsiPoint);
+    LIR_HEADER(OsiPoint)
 };
 
 class LMove
 {
     LAllocation *from_;
     LAllocation *to_;
 
   public:
@@ -97,17 +97,17 @@ class LMove
     }
 };
 
 class LMoveGroup : public LInstructionHelper<0, 0, 0>
 {
     js::Vector<LMove, 2, IonAllocPolicy> moves_;
 
   public:
-    LIR_HEADER(MoveGroup);
+    LIR_HEADER(MoveGroup)
 
     void printOperands(FILE *fp);
 
     // Add a move which takes place simultaneously with all others in the group.
     bool add(LAllocation *from, LAllocation *to);
 
     // Add a move which takes place after existing moves in the group.
     bool addAfter(LAllocation *from, LAllocation *to);
@@ -121,17 +121,17 @@ class LMoveGroup : public LInstructionHe
 };
 
 // Constant 32-bit integer.
 class LInteger : public LInstructionHelper<1, 0, 0>
 {
     int32_t i32_;
 
   public:
-    LIR_HEADER(Integer);
+    LIR_HEADER(Integer)
 
     LInteger(int32_t i32)
       : i32_(i32)
     { }
 
     int32_t getValue() const {
         return i32_;
     }
@@ -146,17 +146,17 @@ class LPointer : public LInstructionHelp
         NON_GC_THING
     };
 
   private:
     void *ptr_;
     Kind kind_;
 
   public:
-    LIR_HEADER(Pointer);
+    LIR_HEADER(Pointer)
 
     LPointer(gc::Cell *ptr)
       : ptr_(ptr), kind_(GC_THING)
     { }
 
     LPointer(void *ptr, Kind kind)
       : ptr_(ptr), kind_(kind)
     { }
@@ -175,63 +175,63 @@ class LPointer : public LInstructionHelp
 };
 
 // A constant Value.
 class LValue : public LInstructionHelper<BOX_PIECES, 0, 0>
 {
     Value v_;
 
   public:
-    LIR_HEADER(Value);
+    LIR_HEADER(Value)
 
     LValue(const Value &v)
       : v_(v)
     { }
 
     Value value() const {
         return v_;
     }
 };
 
 // Formal argument for a function, returning a box. Formal arguments are
 // initially read from the stack.
 class LParameter : public LInstructionHelper<BOX_PIECES, 0, 0>
 {
   public:
-    LIR_HEADER(Parameter);
+    LIR_HEADER(Parameter)
 };
 
 // Stack offset for a word-sized immutable input value to a frame.
 class LCallee : public LInstructionHelper<1, 0, 0>
 {
   public:
-    LIR_HEADER(Callee);
+    LIR_HEADER(Callee)
 };
 
 // Jumps to the start of a basic block.
 class LGoto : public LInstructionHelper<0, 0, 0>
 {
     MBasicBlock *block_;
 
   public:
-    LIR_HEADER(Goto);
+    LIR_HEADER(Goto)
 
     LGoto(MBasicBlock *block)
       : block_(block)
     { }
 
     MBasicBlock *target() const {
         return block_;
     }
 };
 
 class LNewSlots : public LCallInstructionHelper<1, 0, 3>
 {
   public:
-    LIR_HEADER(NewSlots);
+    LIR_HEADER(NewSlots)
 
     LNewSlots(const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3) {
         setTemp(0, temp1);
         setTemp(1, temp2);
         setTemp(2, temp3);
     }
 
     const LDefinition *temp1() {
@@ -247,27 +247,27 @@ class LNewSlots : public LCallInstructio
     MNewSlots *mir() const {
         return mir_->toNewSlots();
     }
 };
 
 class LNewArray : public LInstructionHelper<1, 0, 0>
 {
   public:
-    LIR_HEADER(NewArray);
+    LIR_HEADER(NewArray)
 
     MNewArray *mir() const {
         return mir_->toNewArray();
     }
 };
 
 class LNewObject : public LInstructionHelper<1, 0, 0>
 {
   public:
-    LIR_HEADER(NewObject);
+    LIR_HEADER(NewObject)
 
     MNewObject *mir() const {
         return mir_->toNewObject();
     }
 };
 
 // Allocates a new DeclEnvObject.
 //
@@ -292,34 +292,34 @@ class LNewDeclEnvObject : public LInstru
 // This instruction generates two possible instruction sets:
 //   (1) If the call object is extensible, this is a callVM to create the
 //       call object.
 //   (2) Otherwise, an inline allocation of the call object is attempted.
 //
 class LNewCallObject : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(NewCallObject);
+    LIR_HEADER(NewCallObject)
 
     LNewCallObject(const LAllocation &slots) {
         setOperand(0, slots);
     }
 
     const LAllocation *slots() {
         return getOperand(0);
     }
     MNewCallObject *mir() const {
         return mir_->toNewCallObject();
     }
 };
 
 class LNewStringObject : public LInstructionHelper<1, 1, 1>
 {
   public:
-    LIR_HEADER(NewStringObject);
+    LIR_HEADER(NewStringObject)
 
     LNewStringObject(const LAllocation &input, const LDefinition &temp) {
         setOperand(0, input);
         setTemp(0, temp);
     }
 
     const LAllocation *input() {
         return getOperand(0);
@@ -331,17 +331,17 @@ class LNewStringObject : public LInstruc
         return mir_->toNewStringObject();
     }
 };
 
 // Takes in an Object and a Value.
 class LInitProp : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(InitProp);
+    LIR_HEADER(InitProp)
 
     LInitProp(const LAllocation &object) {
         setOperand(0, object);
     }
 
     static const size_t ValueIndex = 1;
 
     const LAllocation *getObject() {
@@ -354,32 +354,32 @@ class LInitProp : public LCallInstructio
     MInitProp *mir() const {
         return mir_->toInitProp();
     }
 };
 
 class LCheckOverRecursed : public LInstructionHelper<0, 0, 1>
 {
   public:
-    LIR_HEADER(CheckOverRecursed);
+    LIR_HEADER(CheckOverRecursed)
 
     LCheckOverRecursed(const LDefinition &limitreg)
     {
         setTemp(0, limitreg);
     }
 
     const LAllocation *limitTemp() {
         return getTemp(0)->output();
     }
 };
 
 class LDefVar : public LCallInstructionHelper<0, 1, 1>
 {
   public:
-    LIR_HEADER(DefVar);
+    LIR_HEADER(DefVar)
 
     LDefVar(const LAllocation &scopeChain, const LDefinition &namereg)
     {
         setOperand(0, scopeChain);
         setTemp(0, namereg);
     }
 
     const LAllocation *getScopeChain() {
@@ -391,58 +391,58 @@ class LDefVar : public LCallInstructionH
     MDefVar *mir() const {
         return mir_->toDefVar();
     }
 };
 
 class LTypeOfV : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(TypeOfV);
+    LIR_HEADER(TypeOfV)
 
     static const size_t Input = 0;
 
     MTypeOf *mir() const {
         return mir_->toTypeOf();
     }
 };
 
 class LToIdV : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(ToIdV);
+    LIR_HEADER(ToIdV)
 
     static const size_t Object = 0;
     static const size_t Index = BOX_PIECES;
 
     MToId *mir() const {
         return mir_->toToId();
     }
 };
 
 // Allocate an object for |new| on the caller-side.
 // Always performs object initialization with a fast path.
 class LCreateThis : public LInstructionHelper<1, 0, 0>
 {
   public:
-    LIR_HEADER(CreateThis);
+    LIR_HEADER(CreateThis)
 
     LCreateThis()
     { }
 
     MCreateThis *mir() const {
         return mir_->toCreateThis();
     }
 };
 
 // Allocate an object for |new| on the caller-side, when there is no templateObject.
 class LCreateThisVM : public LCallInstructionHelper<1, 2, 0>
 {
   public:
-    LIR_HEADER(CreateThisVM);
+    LIR_HEADER(CreateThisVM)
 
     LCreateThisVM(const LAllocation &callee, const LAllocation &prototype)
     {
         setOperand(0, callee);
         setOperand(1, prototype);
     }
 
     const LAllocation *getCallee() {
@@ -457,17 +457,17 @@ class LCreateThisVM : public LCallInstru
     }
 };
 
 // If the Value is an Object, return unbox(Value).
 // Otherwise, return the other Object.
 class LReturnFromCtor : public LInstructionHelper<1, BOX_PIECES + 1, 0>
 {
   public:
-    LIR_HEADER(ReturnFromCtor);
+    LIR_HEADER(ReturnFromCtor)
 
     LReturnFromCtor(const LAllocation &object)
     {
         // Value set by useBox() during lowering.
         setOperand(LReturnFromCtor::ObjectIndex, object);
     }
 
     const LAllocation *getObject() {
@@ -479,17 +479,17 @@ class LReturnFromCtor : public LInstruct
 };
 
 // Writes a typed argument for a function call to the frame's argument vector.
 class LStackArgT : public LInstructionHelper<0, 1, 0>
 {
     uint32_t argslot_; // Index into frame-scope argument vector.
 
   public:
-    LIR_HEADER(StackArgT);
+    LIR_HEADER(StackArgT)
 
     LStackArgT(uint32_t argslot, const LAllocation &arg)
       : argslot_(argslot)
     {
         setOperand(0, arg);
     }
 
     MPassArg *mir() const {
@@ -504,17 +504,17 @@ class LStackArgT : public LInstructionHe
 };
 
 // Writes an untyped argument for a function call to the frame's argument vector.
 class LStackArgV : public LInstructionHelper<0, BOX_PIECES, 0>
 {
     uint32_t argslot_; // Index into frame-scope argument vector.
 
   public:
-    LIR_HEADER(StackArgV);
+    LIR_HEADER(StackArgV)
 
     LStackArgV(uint32_t argslot)
       : argslot_(argslot)
     { }
 
     uint32_t argslot() const {
         return argslot_;
     }
@@ -563,17 +563,17 @@ class LJSCallInstructionHelper : public 
     typedef LJSCallInstructionHelper<Defs, Operands, Temps> JSCallHelper;
 };
 
 // Generates a polymorphic callsite, wherein the function being called is
 // unknown and anticipated to vary.
 class LCallGeneric : public LJSCallInstructionHelper<BOX_PIECES, 1, 2>
 {
   public:
-    LIR_HEADER(CallGeneric);
+    LIR_HEADER(CallGeneric)
 
     LCallGeneric(const LAllocation &func, uint32_t argslot,
                  const LDefinition &nargsreg, const LDefinition &tmpobjreg)
       : JSCallHelper(argslot)
     {
         setOperand(0, func);
         setTemp(0, nargsreg);
         setTemp(1, tmpobjreg);
@@ -589,17 +589,17 @@ class LCallGeneric : public LJSCallInstr
         return getTemp(1)->output();
     }
 };
 
 // Generates a hardcoded callsite for a known, non-native target.
 class LCallKnown : public LJSCallInstructionHelper<BOX_PIECES, 1, 1>
 {
   public:
-    LIR_HEADER(CallKnown);
+    LIR_HEADER(CallKnown)
 
     LCallKnown(const LAllocation &func, uint32_t argslot, const LDefinition &tmpobjreg)
       : JSCallHelper(argslot)
     {
         setOperand(0, func);
         setTemp(0, tmpobjreg);
     }
 
@@ -610,17 +610,17 @@ class LCallKnown : public LJSCallInstruc
         return getTemp(0)->output();
     }
 };
 
 // Generates a hardcoded callsite for a known, native target.
 class LCallNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 4>
 {
   public:
-    LIR_HEADER(CallNative);
+    LIR_HEADER(CallNative)
 
     LCallNative(uint32_t argslot,
                 const LDefinition &argJSContext, const LDefinition &argUintN,
                 const LDefinition &argVp, const LDefinition &tmpreg)
       : JSCallHelper(argslot)
     {
         // Registers used for callWithABI().
         setTemp(0, argJSContext);
@@ -644,17 +644,17 @@ class LCallNative : public LJSCallInstru
         return getTemp(3)->output();
     }
 };
 
 // Generates a hardcoded callsite for a known, DOM-native target.
 class LCallDOMNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 5>
 {
   public:
-    LIR_HEADER(CallDOMNative);
+    LIR_HEADER(CallDOMNative)
 
     LCallDOMNative(uint32_t argslot,
                    const LDefinition &argJSContext, const LDefinition &argObj,
                    const LDefinition &argPrivate, const LDefinition &argArgc,
                    const LDefinition &argVp)
       : JSCallHelper(argslot)
     {
         setTemp(0, argJSContext);
@@ -681,17 +681,17 @@ class LCallDOMNative : public LJSCallIns
     }
 };
 
 // Generates a polymorphic callsite for |new|, where |this| has not been
 // pre-allocated by the caller.
 class LCallConstructor : public LJSCallInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
-    LIR_HEADER(CallConstructor);
+    LIR_HEADER(CallConstructor)
 
     LCallConstructor(const LAllocation &func, uint32_t argslot)
       : JSCallHelper(argslot)
     {
         setOperand(0, func);
     }
 
     const LAllocation *getFunction() {
@@ -726,33 +726,33 @@ class LDOMPropertyInstructionHelper : pu
         return this->getTemp(2)->output();
     }
 };
 
 
 class LGetDOMProperty : public LDOMPropertyInstructionHelper<BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(GetDOMProperty);
+    LIR_HEADER(GetDOMProperty)
 
     LGetDOMProperty(const LDefinition &JSContextReg, const LAllocation &ObjectReg,
                     const LDefinition &PrivReg, const LDefinition &ValueReg)
       : LDOMPropertyInstructionHelper<BOX_PIECES, 0>(JSContextReg, ObjectReg,
                                                      PrivReg, ValueReg)
     { }
 
     MGetDOMProperty *mir() const {
         return mir_->toGetDOMProperty();
     }
 };
 
 class LSetDOMProperty : public LDOMPropertyInstructionHelper<0, BOX_PIECES>
 {
   public:
-    LIR_HEADER(SetDOMProperty);
+    LIR_HEADER(SetDOMProperty)
 
     LSetDOMProperty(const LDefinition &JSContextReg, const LAllocation &ObjectReg,
                     const LDefinition &PrivReg, const LDefinition &ValueReg)
       : LDOMPropertyInstructionHelper<0, BOX_PIECES>(JSContextReg, ObjectReg,
                                                      PrivReg, ValueReg)
     { }
 
     static const size_t Value = 1;
@@ -762,17 +762,17 @@ class LSetDOMProperty : public LDOMPrope
     }
 };
 
 // Generates a polymorphic callsite, wherein the function being called is
 // unknown and anticipated to vary.
 class LApplyArgsGeneric : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2>
 {
   public:
-    LIR_HEADER(ApplyArgsGeneric);
+    LIR_HEADER(ApplyArgsGeneric)
 
     LApplyArgsGeneric(const LAllocation &func, const LAllocation &argc,
                       const LDefinition &tmpobjreg, const LDefinition &tmpcopy)
     {
         setOperand(0, func);
         setOperand(1, argc);
         setTemp(0, tmpobjreg);
         setTemp(1, tmpcopy);
@@ -807,17 +807,17 @@ class LApplyArgsGeneric : public LCallIn
 
 // Takes in either an integer or boolean input and tests it for truthiness.
 class LTestIAndBranch : public LInstructionHelper<0, 1, 0>
 {
     MBasicBlock *ifTrue_;
     MBasicBlock *ifFalse_;
 
   public:
-    LIR_HEADER(TestIAndBranch);
+    LIR_HEADER(TestIAndBranch)
 
     LTestIAndBranch(const LAllocation &in, MBasicBlock *ifTrue, MBasicBlock *ifFalse)
       : ifTrue_(ifTrue),
         ifFalse_(ifFalse)
     {
         setOperand(0, in);
     }
 
@@ -831,17 +831,17 @@ class LTestIAndBranch : public LInstruct
 
 // Takes in either an integer or boolean input and tests it for truthiness.
 class LTestDAndBranch : public LInstructionHelper<0, 1, 1>
 {
     MBasicBlock *ifTrue_;
     MBasicBlock *ifFalse_;
 
   public:
-    LIR_HEADER(TestDAndBranch);
+    LIR_HEADER(TestDAndBranch)
 
     LTestDAndBranch(const LAllocation &in, MBasicBlock *ifTrue, MBasicBlock *ifFalse)
       : ifTrue_(ifTrue),
         ifFalse_(ifFalse)
     {
         setOperand(0, in);
     }
 
@@ -855,17 +855,17 @@ class LTestDAndBranch : public LInstruct
 
 // Takes in a boxed value and tests it for truthiness.
 class LTestVAndBranch : public LInstructionHelper<0, BOX_PIECES, 1>
 {
     MBasicBlock *ifTrue_;
     MBasicBlock *ifFalse_;
 
   public:
-    LIR_HEADER(TestVAndBranch);
+    LIR_HEADER(TestVAndBranch)
 
     LTestVAndBranch(MBasicBlock *ifTrue, MBasicBlock *ifFalse, const LDefinition &temp)
       : ifTrue_(ifTrue),
         ifFalse_(ifFalse)
     {
         setTemp(0, temp);
     }
 
@@ -878,17 +878,17 @@ class LTestVAndBranch : public LInstruct
     Label *ifTrue();
     Label *ifFalse();
 };
 
 class LPolyInlineDispatch : public LInstructionHelper<0, 1, 1>
 {
   // Accesses function/block table from MIR instruction.
   public:
-    LIR_HEADER(PolyInlineDispatch);
+    LIR_HEADER(PolyInlineDispatch)
 
     LPolyInlineDispatch(const LAllocation &in, const LDefinition &temp) {
         setOperand(0, in);
         setTemp(0, temp);
     }
  
     const LDefinition *temp() {
         return getTemp(0);
@@ -902,17 +902,17 @@ class LPolyInlineDispatch : public LInst
 
 // Compares two integral values of the same JS type, either integer or object.
 // For objects, both operands are in registers.
 class LCompare : public LInstructionHelper<1, 2, 0>
 {
     JSOp jsop_;
 
   public:
-    LIR_HEADER(Compare);
+    LIR_HEADER(Compare)
     LCompare(JSOp jsop, const LAllocation &left, const LAllocation &right)
       : jsop_(jsop)
     {
         setOperand(0, left);
         setOperand(1, right);
     }
 
     JSOp jsop() const {
@@ -927,17 +927,17 @@ class LCompare : public LInstructionHelp
     MCompare *mir() {
         return mir_->toCompare();
     }
 };
 
 class LCompareD : public LInstructionHelper<1, 2, 0>
 {
   public:
-    LIR_HEADER(CompareD);
+    LIR_HEADER(CompareD)
     LCompareD(const LAllocation &left, const LAllocation &right) {
         setOperand(0, left);
         setOperand(1, right);
     }
 
     const LAllocation *left() {
         return getOperand(0);
     }
@@ -947,17 +947,17 @@ class LCompareD : public LInstructionHel
     MCompare *mir() {
         return mir_->toCompare();
     }
 };
 
 class LCompareS : public LInstructionHelper<1, 2, 1>
 {
   public:
-    LIR_HEADER(CompareS);
+    LIR_HEADER(CompareS)
     LCompareS(const LAllocation &left, const LAllocation &right,
               const LDefinition &temp) {
         setOperand(0, left);
         setOperand(1, right);
         setTemp(0, temp);
     }
 
     const LAllocation *left() {
@@ -972,17 +972,17 @@ class LCompareS : public LInstructionHel
     MCompare *mir() {
         return mir_->toCompare();
     }
 };
 
 class LCompareV : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(CompareV);
+    LIR_HEADER(CompareV)
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
     MCompare *mir() const {
         return mir_->toCompare();
     }
 };
@@ -991,17 +991,17 @@ class LCompareV : public LCallInstructio
 // For objects, both operands are in registers.
 class LCompareAndBranch : public LInstructionHelper<0, 2, 0>
 {
     JSOp jsop_;
     MBasicBlock *ifTrue_;
     MBasicBlock *ifFalse_;
 
   public:
-    LIR_HEADER(CompareAndBranch);
+    LIR_HEADER(CompareAndBranch)
     LCompareAndBranch(JSOp jsop, const LAllocation &left, const LAllocation &right,
                       MBasicBlock *ifTrue, MBasicBlock *ifFalse)
       : jsop_(jsop),
         ifTrue_(ifTrue),
         ifFalse_(ifFalse)
     {
         setOperand(0, left);
         setOperand(1, right);
@@ -1028,17 +1028,17 @@ class LCompareAndBranch : public LInstru
 };
 
 class LCompareDAndBranch : public LInstructionHelper<0, 2, 0>
 {
     MBasicBlock *ifTrue_;
     MBasicBlock *ifFalse_;
 
   public:
-    LIR_HEADER(CompareDAndBranch);
+    LIR_HEADER(CompareDAndBranch)
     LCompareDAndBranch(const LAllocation &left, const LAllocation &right,
                        MBasicBlock *ifTrue, MBasicBlock *ifFalse)
       : ifTrue_(ifTrue),
         ifFalse_(ifFalse)
     {
         setOperand(0, left);
         setOperand(1, right);
     }
@@ -1061,17 +1061,17 @@ class LCompareDAndBranch : public LInstr
 };
 
 // Used for strict-equality comparisons where one side is a boolean
 // and the other is a value. Note that CompareI is used to compare
 // two booleans.
 class LCompareB : public LInstructionHelper<1, BOX_PIECES + 1, 0>
 {
   public:
-    LIR_HEADER(CompareB);
+    LIR_HEADER(CompareB)
 
     LCompareB(const LAllocation &rhs) {
         setOperand(BOX_PIECES, rhs);
     }
 
     static const size_t Lhs = 0;
 
     const LAllocation *rhs() {
@@ -1084,17 +1084,17 @@ class LCompareB : public LInstructionHel
 };
 
 class LCompareBAndBranch : public LInstructionHelper<0, BOX_PIECES + 1, 0>
 {
     MBasicBlock *ifTrue_;
     MBasicBlock *ifFalse_;
 
   public:
-    LIR_HEADER(CompareBAndBranch);
+    LIR_HEADER(CompareBAndBranch)
 
     LCompareBAndBranch(const LAllocation &rhs, MBasicBlock *ifTrue, MBasicBlock *ifFalse)
       : ifTrue_(ifTrue), ifFalse_(ifFalse)
     {
         setOperand(BOX_PIECES, rhs);
     }
 
     static const size_t Lhs = 0;
@@ -1112,32 +1112,32 @@ class LCompareBAndBranch : public LInstr
     MCompare *mir() {
         return mir_->toCompare();
     }
 };
 
 class LIsNullOrUndefined : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(IsNullOrUndefined);
+    LIR_HEADER(IsNullOrUndefined)
 
     static const size_t Value = 0;
 
     MCompare *mir() {
         return mir_->toCompare();
     }
 };
 
 class LIsNullOrUndefinedAndBranch : public LInstructionHelper<0, BOX_PIECES, 0>
 {
     MBasicBlock *ifTrue_;
     MBasicBlock *ifFalse_;
 
   public:
-    LIR_HEADER(IsNullOrUndefinedAndBranch);
+    LIR_HEADER(IsNullOrUndefinedAndBranch)
 
     LIsNullOrUndefinedAndBranch(MBasicBlock *ifTrue, MBasicBlock *ifFalse)
       : ifTrue_(ifTrue), ifFalse_(ifFalse)
     { }
 
     static const size_t Value = 0;
 
     MBasicBlock *ifTrue() const {
@@ -1150,39 +1150,39 @@ class LIsNullOrUndefinedAndBranch : publ
         return mir_->toCompare();
     }
 };
 
 // Not operation on an integer.
 class LNotI : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(NotI);
+    LIR_HEADER(NotI)
 
     LNotI(const LAllocation &input) {
         setOperand(0, input);
     }
 };
 
 // Not operation on a double.
 class LNotD : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(NotD);
+    LIR_HEADER(NotD)
 
     LNotD(const LAllocation &input) {
         setOperand(0, input);
     }
 };
 
 // Boolean complement operation on a value.
 class LNotV : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
-    LIR_HEADER(NotV);
+    LIR_HEADER(NotV)
 
     static const size_t Input = 0;
     LNotV(const LDefinition &temp)
     {
         setTemp(0, temp);
     }
 
     const LAllocation *tempFloat() {
@@ -1190,53 +1190,53 @@ class LNotV : public LInstructionHelper<
     }
 };
 
 // Bitwise not operation, takes a 32-bit integer as input and returning
 // a 32-bit integer result as an output.
 class LBitNotI : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(BitNotI);
+    LIR_HEADER(BitNotI)
 };
 
 // Call a VM function to perform a BITNOT operation.
 class LBitNotV : public LCallInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(BitNotV);
+    LIR_HEADER(BitNotV)
 
     static const size_t Input = 0;
 };
 
 // Binary bitwise operation, taking two 32-bit integers as inputs and returning
 // a 32-bit integer result as an output.
 class LBitOpI : public LInstructionHelper<1, 2, 0>
 {
     JSOp op_;
 
   public:
-    LIR_HEADER(BitOpI);
+    LIR_HEADER(BitOpI)
 
     LBitOpI(JSOp op)
       : op_(op)
     { }
 
     JSOp bitop() {
         return op_;
     }
 };
 
 // Call a VM function to perform a bitwise operation.
 class LBitOpV : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
     JSOp jsop_;
 
   public:
-    LIR_HEADER(BitOpV);
+    LIR_HEADER(BitOpV)
 
     LBitOpV(JSOp jsop)
       : jsop_(jsop)
     { }
 
     JSOp jsop() const {
         return jsop_;
     }
@@ -1247,17 +1247,17 @@ class LBitOpV : public LCallInstructionH
 
 // Shift operation, taking two 32-bit integers as inputs and returning
 // a 32-bit integer result as an output.
 class LShiftI : public LBinaryMath<0>
 {
     JSOp op_;
 
   public:
-    LIR_HEADER(ShiftI);
+    LIR_HEADER(ShiftI)
 
     LShiftI(JSOp op)
       : op_(op)
     { }
 
     JSOp bitop() {
         return op_;
     }
@@ -1265,48 +1265,48 @@ class LShiftI : public LBinaryMath<0>
     MInstruction *mir() {
         return mir_->toInstruction();
     }
 };
 
 class LUrshD : public LBinaryMath<1>
 {
   public:
-    LIR_HEADER(UrshD);
+    LIR_HEADER(UrshD)
 
     LUrshD(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
     const LDefinition *temp() {
         return getTemp(0);
     }
 };
 
 // Returns from the function being compiled (not used in inlined frames). The
 // input must be a box.
 class LReturn : public LInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(Return);
+    LIR_HEADER(Return)
 };
 
 class LThrow : public LCallInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(Throw);
+    LIR_HEADER(Throw)
 
     static const size_t Value = 0;
 };
 
 class LMinMaxI : public LInstructionHelper<1, 2, 0>
 {
   public:
-    LIR_HEADER(MinMaxI);
+    LIR_HEADER(MinMaxI)
     LMinMaxI(const LAllocation &first, const LAllocation &second)
     {
         setOperand(0, first);
         setOperand(1, second);
     }
 
     const LAllocation *first() {
         return this->getOperand(0);
@@ -1320,17 +1320,17 @@ class LMinMaxI : public LInstructionHelp
     MMinMax *mir() const {
         return mir_->toMinMax();
     }
 };
 
 class LMinMaxD : public LInstructionHelper<1, 2, 0>
 {
   public:
-    LIR_HEADER(MinMaxD);
+    LIR_HEADER(MinMaxD)
     LMinMaxD(const LAllocation &first, const LAllocation &second) 
     {
         setOperand(0, first);
         setOperand(1, second);
     }
 
     const LAllocation *first() {
         return this->getOperand(0);
@@ -1345,57 +1345,57 @@ class LMinMaxD : public LInstructionHelp
         return mir_->toMinMax();
     }
 };
 
 // Negative of a double.
 class LNegD : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(NegD);
+    LIR_HEADER(NegD)
     LNegD(const LAllocation &num) {
         setOperand(0, num);
     }
 };
 
 // Absolute value of an integer.
 class LAbsI : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(AbsI);
+    LIR_HEADER(AbsI)
     LAbsI(const LAllocation &num) {
         setOperand(0, num);
     }
 };
 
 // Absolute value of a double.
 class LAbsD : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(AbsD);
+    LIR_HEADER(AbsD)
     LAbsD(const LAllocation &num) {
         setOperand(0, num);
     }
 };
 
 // Square root of a double.
 class LSqrtD : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(SqrtD);
+    LIR_HEADER(SqrtD)
     LSqrtD(const LAllocation &num) {
         setOperand(0, num);
     }
 };
 
 // Double raised to an integer power.
 class LPowI : public LCallInstructionHelper<1, 2, 1>
 {
   public:
-    LIR_HEADER(PowI);
+    LIR_HEADER(PowI)
     LPowI(const LAllocation &value, const LAllocation &power, const LDefinition &temp) {
         setOperand(0, value);
         setOperand(1, power);
         setTemp(0, temp);
     }
 
     const LAllocation *value() {
         return getOperand(0);
@@ -1407,17 +1407,17 @@ class LPowI : public LCallInstructionHel
         return getTemp(0);
     }
 };
 
 // Double raised to a double power.
 class LPowD : public LCallInstructionHelper<1, 2, 1>
 {
   public:
-    LIR_HEADER(PowD);
+    LIR_HEADER(PowD)
     LPowD(const LAllocation &value, const LAllocation &power, const LDefinition &temp) {
         setOperand(0, value);
         setOperand(1, power);
         setTemp(0, temp);
     }
 
     const LAllocation *value() {
         return getOperand(0);
@@ -1429,33 +1429,33 @@ class LPowD : public LCallInstructionHel
         return getTemp(0);
     }
 };
 
 // Math.random().
 class LRandom : public LCallInstructionHelper<1, 0, 2>
 {
   public:
-    LIR_HEADER(Random);
+    LIR_HEADER(Random)
     LRandom(const LDefinition &temp, const LDefinition &temp2) {
         setTemp(0, temp);
         setTemp(1, temp2);
     }
     const LDefinition *temp() {
         return getTemp(0);
     }
     const LDefinition *temp2() {
         return getTemp(1);
     }
 };
 
 class LMathFunctionD : public LCallInstructionHelper<1, 1, 1>
 {
   public:
-    LIR_HEADER(MathFunctionD);
+    LIR_HEADER(MathFunctionD)
     LMathFunctionD(const LAllocation &input, const LDefinition &temp) {
         setOperand(0, input);
         setTemp(0, temp);
     }
 
     const LDefinition *temp() {
         return getTemp(0);
     }
@@ -1465,17 +1465,17 @@ class LMathFunctionD : public LCallInstr
 };
 
 // Adds two integers, returning an integer value.
 class LAddI : public LBinaryMath<0>
 {
     bool recoversInput_;
 
   public:
-    LIR_HEADER(AddI);
+    LIR_HEADER(AddI)
 
     LAddI()
       : recoversInput_(false)
     { }
 
     virtual bool recoversInput() const {
         return recoversInput_;
     }
@@ -1485,17 +1485,17 @@ class LAddI : public LBinaryMath<0>
 };
 
 // Subtracts two integers, returning an integer value.
 class LSubI : public LBinaryMath<0>
 {
     bool recoversInput_;
 
   public:
-    LIR_HEADER(SubI);
+    LIR_HEADER(SubI)
 
     LSubI()
       : recoversInput_(false)
     { }
 
     virtual bool recoversInput() const {
         return recoversInput_;
     }
@@ -1505,31 +1505,31 @@ class LSubI : public LBinaryMath<0>
 };
 
 // Performs an add, sub, mul, or div on two double values.
 class LMathD : public LBinaryMath<0>
 {
     JSOp jsop_;
 
   public:
-    LIR_HEADER(MathD);
+    LIR_HEADER(MathD)
 
     LMathD(JSOp jsop)
       : jsop_(jsop)
     { }
 
     JSOp jsop() const {
         return jsop_;
     }
 };
 
 class LModD : public LBinaryMath<1>
 {
   public:
-    LIR_HEADER(ModD);
+    LIR_HEADER(ModD)
 
     LModD(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
     const LDefinition *temp() {
         return getTemp(0);
@@ -1540,18 +1540,18 @@ class LModD : public LBinaryMath<1>
 };
 
 // Call a VM function to perform a binary operation.
 class LBinaryV : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
     JSOp jsop_;
 
   public:
-    LIR_HEADER(BinaryV);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(BinaryV)
+    BOX_OUTPUT_ACCESSORS()
 
     LBinaryV(JSOp jsop)
       : jsop_(jsop)
     { }
 
     JSOp jsop() const {
         return jsop_;
     }
@@ -1559,17 +1559,17 @@ class LBinaryV : public LCallInstruction
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 };
 
 // Adds two string, returning a string.
 class LConcat : public LCallInstructionHelper<1, 2, 0>
 {
   public:
-    LIR_HEADER(Concat);
+    LIR_HEADER(Concat)
 
     LConcat(const LAllocation &lhs, const LAllocation &rhs) {
         setOperand(0, lhs);
         setOperand(1, rhs);
     }
 
     const LAllocation *lhs() {
         return this->getOperand(0);
@@ -1578,17 +1578,17 @@ class LConcat : public LCallInstructionH
         return this->getOperand(1);
     }
 };
 
 // Get uint16 character code from a string.
 class LCharCodeAt : public LInstructionHelper<1, 2, 0>
 {
   public:
-    LIR_HEADER(CharCodeAt);
+    LIR_HEADER(CharCodeAt)
 
     LCharCodeAt(const LAllocation &str, const LAllocation &index) {
         setOperand(0, str);
         setOperand(1, index);
     }
 
     const LAllocation *str() {
         return this->getOperand(0);
@@ -1597,43 +1597,43 @@ class LCharCodeAt : public LInstructionH
         return this->getOperand(1);
     }
 };
 
 // Convert uint16 character code to a string.
 class LFromCharCode : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(FromCharCode);
+    LIR_HEADER(FromCharCode)
 
     LFromCharCode(const LAllocation &code) {
         setOperand(0, code);
     }
 
     const LAllocation *code() {
         return this->getOperand(0);
     }
 };
 
 // Convert a 32-bit integer to a double.
 class LInt32ToDouble : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(Int32ToDouble);
+    LIR_HEADER(Int32ToDouble)
 
     LInt32ToDouble(const LAllocation &input) {
         setOperand(0, input);
     }
 };
 
 // Convert a value to a double.
 class LValueToDouble : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(ValueToDouble);
+    LIR_HEADER(ValueToDouble)
     static const size_t Input = 0;
 };
 
 // Convert a value to an int32.
 //   Input: components of a Value
 //   Output: 32-bit integer
 //   Bailout: undefined, string, object, or non-int32 double
 //   Temps: one float register
@@ -1646,17 +1646,17 @@ class LValueToInt32 : public LInstructio
         NORMAL,
         TRUNCATE
     };
 
   private:
     Mode mode_;
 
   public:
-    LIR_HEADER(ValueToInt32);
+    LIR_HEADER(ValueToInt32)
 
     LValueToInt32(const LDefinition &temp, Mode mode)
       : mode_(mode)
     {
         setTemp(0, temp);
     }
 
     static const size_t Input = 0;
@@ -1674,17 +1674,17 @@ class LValueToInt32 : public LInstructio
 
 // Convert a double to an int32.
 //   Input: floating-point register
 //   Output: 32-bit integer
 //   Bailout: if the double cannot be converted to an integer.
 class LDoubleToInt32 : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(DoubleToInt32);
+    LIR_HEADER(DoubleToInt32)
 
     LDoubleToInt32(const LAllocation &in) {
         setOperand(0, in);
     }
 
     MToInt32 *mir() const {
         return mir_->toToInt32();
     }
@@ -1692,63 +1692,63 @@ class LDoubleToInt32 : public LInstructi
 
 
 // Convert a double to a truncated int32.
 //   Input: floating-point register
 //   Output: 32-bit integer
 class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1>
 {
   public:
-    LIR_HEADER(TruncateDToInt32);
+    LIR_HEADER(TruncateDToInt32)
 
     LTruncateDToInt32(const LAllocation &in, const LDefinition &temp) {
         setOperand(0, in);
         setTemp(0, temp);
     }
 
     const LDefinition *tempFloat() {
         return getTemp(0);
     }
 };
 
 // Convert a any input type hosted on one definition to a string with a function
 // call.
 class LIntToString : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(IntToString);
+    LIR_HEADER(IntToString)
 
     LIntToString(const LAllocation &input) {
         setOperand(0, input);
     }
 
     const MToString *mir() {
         return mir_->toToString();
     }
 };
 
 // No-op instruction that is used to hold the entry snapshot. This simplifies
 // register allocation as it doesn't need to sniff the snapshot out of the
 // LIRGraph.
 class LStart : public LInstructionHelper<0, 0, 0>
 {
   public:
-    LIR_HEADER(Start);
+    LIR_HEADER(Start)
 };
 
 // Passed the StackFrame address in the OsrFrameReg by SideCannon().
 // Forwards this object to the LOsrValues for Value materialization.
 class LOsrEntry : public LInstructionHelper<1, 0, 0>
 {
   protected:
     Label label_;
     uint32_t frameDepth_;
 
   public:
-    LIR_HEADER(OsrEntry);
+    LIR_HEADER(OsrEntry)
 
     LOsrEntry()
       : frameDepth_(0)
     { }
 
     void setFrameDepth(uint32_t depth) {
         frameDepth_ = depth;
     }
@@ -1760,58 +1760,58 @@ class LOsrEntry : public LInstructionHel
     }
 
 };
 
 // Materialize a Value stored in an interpreter frame for OSR.
 class LOsrValue : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
-    LIR_HEADER(OsrValue);
+    LIR_HEADER(OsrValue)
 
     LOsrValue(const LAllocation &entry)
     {
         setOperand(0, entry);
     }
 
     const MOsrValue *mir() {
         return mir_->toOsrValue();
     }
 };
 
 // Materialize a JSObject scope chain stored in an interpreter frame for OSR.
 class LOsrScopeChain : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(OsrScopeChain);
+    LIR_HEADER(OsrScopeChain)
 
     LOsrScopeChain(const LAllocation &entry)
     {
         setOperand(0, entry);
     }
 
     const MOsrScopeChain *mir() {
         return mir_->toOsrScopeChain();
     }
 };
 
 class LRegExp : public LCallInstructionHelper<1, 0, 0>
 {
   public:
-    LIR_HEADER(RegExp);
+    LIR_HEADER(RegExp)
 
     const MRegExp *mir() const {
         return mir_->toRegExp();
     }
 };
 
 class LRegExpTest : public LCallInstructionHelper<1, 2, 0>
 {
   public:
-    LIR_HEADER(RegExpTest);
+    LIR_HEADER(RegExpTest)
 
     LRegExpTest(const LAllocation &regexp, const LAllocation &string)
     {
         setOperand(0, regexp);
         setOperand(1, string);
     }
 
     const LAllocation *regexp() {
@@ -1824,52 +1824,52 @@ class LRegExpTest : public LCallInstruct
     const MRegExpTest *mir() const {
         return mir_->toRegExpTest();
     }
 };
 
 class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(LambdaForSingleton);
+    LIR_HEADER(LambdaForSingleton)
 
     LLambdaForSingleton(const LAllocation &scopeChain)
     {
         setOperand(0, scopeChain);
     }
     const LAllocation *scopeChain() {
         return getOperand(0);
     }
     const MLambda *mir() const {
         return mir_->toLambda();
     }
 };
 
 class LLambda : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(Lambda);
+    LIR_HEADER(Lambda)
 
     LLambda(const LAllocation &scopeChain) {
         setOperand(0, scopeChain);
     }
     const LAllocation *scopeChain() {
         return getOperand(0);
     }
     const MLambda *mir() const {
         return mir_->toLambda();
     }
 };
 
 // Determines the implicit |this| value for function calls.
 class LImplicitThis : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
-    LIR_HEADER(ImplicitThis);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(ImplicitThis)
+    BOX_OUTPUT_ACCESSORS()
 
     LImplicitThis(const LAllocation &callee) {
         setOperand(0, callee);
     }
 
     const MImplicitThis *mir() const {
         return mir_->toImplicitThis();
     }
@@ -1879,64 +1879,64 @@ class LImplicitThis : public LInstructio
 };
 
 // Load the "slots" member out of a JSObject.
 //   Input: JSObject pointer
 //   Output: slots pointer
 class LSlots : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(Slots);
+    LIR_HEADER(Slots)
 
     LSlots(const LAllocation &object) {
         setOperand(0, object);
     }
 
     const LAllocation *object() {
         return getOperand(0);
     }
 };
 
 // Load the "elements" member out of a JSObject.
 //   Input: JSObject pointer
 //   Output: elements pointer
 class LElements : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(Elements);
+    LIR_HEADER(Elements)
 
     LElements(const LAllocation &object) {
         setOperand(0, object);
     }
 
     const LAllocation *object() {
         return getOperand(0);
     }
 };
 
 // Load a dense array's initialized length from an elements vector.
 class LInitializedLength : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(InitializedLength);
+    LIR_HEADER(InitializedLength)
 
     LInitializedLength(const LAllocation &elements) {
         setOperand(0, elements);
     }
 
     const LAllocation *elements() {
         return getOperand(0);
     }
 };
 
 // Set a dense array's initialized length to an elements vector.
 class LSetInitializedLength : public LInstructionHelper<0, 2, 0>
 {
   public:
-    LIR_HEADER(SetInitializedLength);
+    LIR_HEADER(SetInitializedLength)
 
     LSetInitializedLength(const LAllocation &elements, const LAllocation &index) {
         setOperand(0, elements);
         setOperand(1, index);
     }
 
     const LAllocation *elements() {
         return getOperand(0);
@@ -1945,61 +1945,61 @@ class LSetInitializedLength : public LIn
         return getOperand(1);
     }
 };
 
 // Read length field of an object element.
 class LArrayLength : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(ArrayLength);
+    LIR_HEADER(ArrayLength)
 
     LArrayLength(const LAllocation &elements) {
         setOperand(0, elements);
     }
 
     const LAllocation *elements() {
         return getOperand(0);
     }
 };
 
 // Read the length of a typed array.
 class LTypedArrayLength : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(TypedArrayLength);
+    LIR_HEADER(TypedArrayLength)
 
     LTypedArrayLength(const LAllocation &obj) {
         setOperand(0, obj);
     }
 
     const LAllocation *object() {
         return getOperand(0);
     }
 };
 
 // Load a typed array's elements vector.
 class LTypedArrayElements : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(TypedArrayElements);
+    LIR_HEADER(TypedArrayElements)
 
     LTypedArrayElements(const LAllocation &object) {
         setOperand(0, object);
     }
     const LAllocation *object() {
         return getOperand(0);
     }
 };
 
 // Bailout if index >= length.
 class LBoundsCheck : public LInstructionHelper<0, 2, 0>
 {
   public:
-    LIR_HEADER(BoundsCheck);
+    LIR_HEADER(BoundsCheck)
 
     LBoundsCheck(const LAllocation &index, const LAllocation &length) {
         setOperand(0, index);
         setOperand(1, length);
     }
     const MBoundsCheck *mir() const {
         return mir_->toBoundsCheck();
     }
@@ -2010,17 +2010,17 @@ class LBoundsCheck : public LInstruction
         return getOperand(1);
     }
 };
 
 // Bailout if index + minimum < 0 or index + maximum >= length.
 class LBoundsCheckRange : public LInstructionHelper<0, 2, 1>
 {
   public:
-    LIR_HEADER(BoundsCheckRange);
+    LIR_HEADER(BoundsCheckRange)
 
     LBoundsCheckRange(const LAllocation &index, const LAllocation &length,
                       const LDefinition &temp)
     {
         setOperand(0, index);
         setOperand(1, length);
         setTemp(0, temp);
     }
@@ -2034,17 +2034,17 @@ class LBoundsCheckRange : public LInstru
         return getOperand(1);
     }
 };
 
 // Bailout if index < minimum.
 class LBoundsCheckLower : public LInstructionHelper<0, 1, 0>
 {
   public:
-    LIR_HEADER(BoundsCheckLower);
+    LIR_HEADER(BoundsCheckLower)
 
     LBoundsCheckLower(const LAllocation &index)
     {
         setOperand(0, index);
     }
     MBoundsCheckLower *mir() const {
         return mir_->toBoundsCheckLower();
     }
@@ -2052,18 +2052,18 @@ class LBoundsCheckLower : public LInstru
         return getOperand(0);
     }
 };
 
 // Load a value from a dense array's elements vector. Bail out if it's the hole value.
 class LLoadElementV : public LInstructionHelper<BOX_PIECES, 2, 0>
 {
   public:
-    LIR_HEADER(LoadElementV);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(LoadElementV)
+    BOX_OUTPUT_ACCESSORS()
 
     LLoadElementV(const LAllocation &elements, const LAllocation &index) {
         setOperand(0, elements);
         setOperand(1, index);
     }
     const MLoadElement *mir() const {
         return mir_->toLoadElement();
     }
@@ -2073,17 +2073,17 @@ class LLoadElementV : public LInstructio
     const LAllocation *index() {
         return getOperand(1);
     }
 };
 
 class LInArray : public LInstructionHelper<1, 3, 0>
 {
   public:
-    LIR_HEADER(InArray);
+    LIR_HEADER(InArray)
 
     LInArray(const LAllocation &elements, const LAllocation &index, const LAllocation &initLength) {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, initLength);
     }
     const MInArray *mir() const {
         return mir_->toInArray();
@@ -2099,18 +2099,18 @@ class LInArray : public LInstructionHelp
     }
 };
 
 
 // Load a value from a dense array's elements vector. Bail out if it's the hole value.
 class LLoadElementHole : public LInstructionHelper<BOX_PIECES, 3, 0>
 {
   public:
-    LIR_HEADER(LoadElementHole);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(LoadElementHole)
+    BOX_OUTPUT_ACCESSORS()
 
     LLoadElementHole(const LAllocation &elements, const LAllocation &index, const LAllocation &initLength) {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, initLength);
     }
     const MLoadElementHole *mir() const {
         return mir_->toLoadElementHole();
@@ -2128,17 +2128,17 @@ class LLoadElementHole : public LInstruc
 
 // Load a typed value from a dense array's elements vector. The array must be
 // known to be packed, so that we don't have to check for the hole value.
 // This instruction does not load the type tag and can directly load into a
 // FP register.
 class LLoadElementT : public LInstructionHelper<1, 2, 0>
 {
   public:
-    LIR_HEADER(LoadElementT);
+    LIR_HEADER(LoadElementT)
 
     LLoadElementT(const LAllocation &elements, const LAllocation &index) {
         setOperand(0, elements);
         setOperand(1, index);
     }
     const MLoadElement *mir() const {
         return mir_->toLoadElement();
     }
@@ -2149,17 +2149,17 @@ class LLoadElementT : public LInstructio
         return getOperand(1);
     }
 };
 
 // Store a boxed value to a dense array's element vector.
 class LStoreElementV : public LInstructionHelper<0, 2 + BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(StoreElementV);
+    LIR_HEADER(StoreElementV)
 
     LStoreElementV(const LAllocation &elements, const LAllocation &index) {
         setOperand(0, elements);
         setOperand(1, index);
     }
 
     static const size_t Value = 2;
 
@@ -2176,17 +2176,17 @@ class LStoreElementV : public LInstructi
 
 // Store a typed value to a dense array's elements vector. Compared to
 // LStoreElementV, this instruction can store doubles and constants directly,
 // and does not store the type tag if the array is monomorphic and known to
 // be packed.
 class LStoreElementT : public LInstructionHelper<0, 3, 0>
 {
   public:
-    LIR_HEADER(StoreElementT);
+    LIR_HEADER(StoreElementT)
 
     LStoreElementT(const LAllocation &elements, const LAllocation &index, const LAllocation &value) {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
     }
 
     const MStoreElement *mir() const {
@@ -2202,17 +2202,17 @@ class LStoreElementT : public LInstructi
         return getOperand(2);
     }
 };
 
 // Like LStoreElementV, but supports indexes >= initialized length.
 class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(StoreElementHoleV);
+    LIR_HEADER(StoreElementHoleV)
 
     LStoreElementHoleV(const LAllocation &object, const LAllocation &elements,
                        const LAllocation &index) {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
     }
 
@@ -2231,17 +2231,17 @@ class LStoreElementHoleV : public LInstr
         return getOperand(2);
     }
 };
 
 // Like LStoreElementT, but supports indexes >= initialized length.
 class LStoreElementHoleT : public LInstructionHelper<0, 4, 0>
 {
   public:
-    LIR_HEADER(StoreElementHoleT);
+    LIR_HEADER(StoreElementHoleT)
 
     LStoreElementHoleT(const LAllocation &object, const LAllocation &elements,
                        const LAllocation &index, const LAllocation &value) {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
         setOperand(3, value);
     }
@@ -2261,17 +2261,17 @@ class LStoreElementHoleT : public LInstr
     const LAllocation *value() {
         return getOperand(3);
     }
 };
 
 class LArrayPopShiftV : public LInstructionHelper<BOX_PIECES, 1, 2>
 {
   public:
-    LIR_HEADER(ArrayPopShiftV);
+    LIR_HEADER(ArrayPopShiftV)
 
     LArrayPopShiftV(const LAllocation &object, const LDefinition &temp0, const LDefinition &temp1) {
         setOperand(0, object);
         setTemp(0, temp0);
         setTemp(1, temp1);
     }
 
     const MArrayPopShift *mir() const {
@@ -2286,17 +2286,17 @@ class LArrayPopShiftV : public LInstruct
     const LDefinition *temp1() {
         return getTemp(1);
     }
 };
 
 class LArrayPopShiftT : public LInstructionHelper<1, 1, 2>
 {
   public:
-    LIR_HEADER(ArrayPopShiftT);
+    LIR_HEADER(ArrayPopShiftT)
 
     LArrayPopShiftT(const LAllocation &object, const LDefinition &temp0, const LDefinition &temp1) {
         setOperand(0, object);
         setTemp(0, temp0);
         setTemp(1, temp1);
     }
 
     const MArrayPopShift *mir() const {
@@ -2311,17 +2311,17 @@ class LArrayPopShiftT : public LInstruct
     const LDefinition *temp1() {
         return getTemp(1);
     }
 };
 
 class LArrayPushV : public LInstructionHelper<1, 1 + BOX_PIECES, 1>
 {
   public:
-    LIR_HEADER(ArrayPushV);
+    LIR_HEADER(ArrayPushV)
 
     LArrayPushV(const LAllocation &object, const LDefinition &temp) {
         setOperand(0, object);
         setTemp(0, temp);
     }
 
     static const size_t Value = 1;
 
@@ -2334,17 +2334,17 @@ class LArrayPushV : public LInstructionH
     const LDefinition *temp() {
         return getTemp(0);
     }
 };
 
 class LArrayPushT : public LInstructionHelper<1, 2, 1>
 {
   public:
-    LIR_HEADER(ArrayPushT);
+    LIR_HEADER(ArrayPushT)
 
     LArrayPushT(const LAllocation &object, const LAllocation &value, const LDefinition &temp) {
         setOperand(0, object);
         setOperand(1, value);
         setTemp(0, temp);
     }
 
     const MArrayPush *mir() const {
@@ -2359,17 +2359,17 @@ class LArrayPushT : public LInstructionH
     const LDefinition *temp() {
         return getTemp(0);
     }
 };
 
 class LArrayConcat : public LCallInstructionHelper<1, 2, 2>
 {
   public:
-    LIR_HEADER(ArrayConcat);
+    LIR_HEADER(ArrayConcat)
 
     LArrayConcat(const LAllocation &lhs, const LAllocation &rhs,
                  const LDefinition &temp1, const LDefinition &temp2) {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
@@ -2389,17 +2389,17 @@ class LArrayConcat : public LCallInstruc
         return getTemp(1);
     }
 };
 
 // Load a typed value from a typed array's elements vector.
 class LLoadTypedArrayElement : public LInstructionHelper<1, 2, 1>
 {
   public:
-    LIR_HEADER(LoadTypedArrayElement);
+    LIR_HEADER(LoadTypedArrayElement)
 
     LLoadTypedArrayElement(const LAllocation &elements, const LAllocation &index,
                            const LDefinition &temp) {
         setOperand(0, elements);
         setOperand(1, index);
         setTemp(0, temp);
     }
     const MLoadTypedArrayElement *mir() const {
@@ -2414,18 +2414,18 @@ class LLoadTypedArrayElement : public LI
     const LDefinition *temp() {
         return getTemp(0);
     }
 };
 
 class LLoadTypedArrayElementHole : public LInstructionHelper<BOX_PIECES, 2, 0>
 {
   public:
-    LIR_HEADER(LoadTypedArrayElementHole);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(LoadTypedArrayElementHole)
+    BOX_OUTPUT_ACCESSORS()
 
     LLoadTypedArrayElementHole(const LAllocation &object, const LAllocation &index) {
         setOperand(0, object);
         setOperand(1, index);
     }
     const MLoadTypedArrayElementHole *mir() const {
         return mir_->toLoadTypedArrayElementHole();
     }
@@ -2435,17 +2435,17 @@ class LLoadTypedArrayElementHole : publi
     const LAllocation *index() {
         return getOperand(1);
     }
 };
 
 class LStoreTypedArrayElement : public LInstructionHelper<0, 3, 0>
 {
   public:
-    LIR_HEADER(StoreTypedArrayElement);
+    LIR_HEADER(StoreTypedArrayElement)
 
     LStoreTypedArrayElement(const LAllocation &elements, const LAllocation &index,
                             const LAllocation &value) {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
     }
 
@@ -2461,84 +2461,84 @@ class LStoreTypedArrayElement : public L
     const LAllocation *value() {
         return getOperand(2);
     }
 };
 
 class LClampIToUint8 : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(ClampIToUint8);
+    LIR_HEADER(ClampIToUint8)
 
     LClampIToUint8(const LAllocation &in) {
         setOperand(0, in);
     }
 };
 
 class LClampDToUint8 : public LInstructionHelper<1, 1, 1>
 {
   public:
-    LIR_HEADER(ClampDToUint8);
+    LIR_HEADER(ClampDToUint8)
 
     LClampDToUint8(const LAllocation &in, const LDefinition &temp) {
         setOperand(0, in);
         setTemp(0, temp);
     }
 };
 
 class LClampVToUint8 : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
-    LIR_HEADER(ClampVToUint8);
+    LIR_HEADER(ClampVToUint8)
 
     LClampVToUint8(const LDefinition &tempFloat) {
         setTemp(0, tempFloat);
     }
 
     static const size_t Input = 0;
 
     const LDefinition *tempFloat() {
         return getTemp(0);
     }
 };
 
 // Load a boxed value from an object's fixed slot.
 class LLoadFixedSlotV : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
-    LIR_HEADER(LoadFixedSlotV);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(LoadFixedSlotV)
+    BOX_OUTPUT_ACCESSORS()
 
     LLoadFixedSlotV(const LAllocation &object) {
         setOperand(0, object);
     }
     const MLoadFixedSlot *mir() const {
         return mir_->toLoadFixedSlot();
     }
 };
 
 // Load a typed value from an object's fixed slot.
 class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(LoadFixedSlotT);
+    LIR_HEADER(LoadFixedSlotT)
 
     LLoadFixedSlotT(const LAllocation &object) {
         setOperand(0, object);
     }
     const MLoadFixedSlot *mir() const {
         return mir_->toLoadFixedSlot();
     }
 };
 
 // Store a boxed value to an object's fixed slot.
 class LStoreFixedSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(StoreFixedSlotV);
+    LIR_HEADER(StoreFixedSlotV)
 
     LStoreFixedSlotV(const LAllocation &obj) {
         setOperand(0, obj);
     }
 
     static const size_t Value = 1;
 
     const MStoreFixedSlot *mir() const {
@@ -2548,17 +2548,17 @@ class LStoreFixedSlotV : public LInstruc
         return getOperand(0);
     }
 };
 
 // Store a typed value to an object's fixed slot.
 class LStoreFixedSlotT : public LInstructionHelper<0, 2, 0>
 {
   public:
-    LIR_HEADER(StoreFixedSlotT);
+    LIR_HEADER(StoreFixedSlotT)
 
     LStoreFixedSlotT(const LAllocation &obj, const LAllocation &value)
     {
         setOperand(0, obj);
         setOperand(1, value);
     }
     const MStoreFixedSlot *mir() const {
         return mir_->toStoreFixedSlot();
@@ -2570,77 +2570,77 @@ class LStoreFixedSlotT : public LInstruc
         return getOperand(1);
     }
 };
 
 // Note, Name ICs always return a Value. There are no V/T variants.
 class LGetNameCache : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
-    LIR_HEADER(GetNameCache);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(GetNameCache)
+    BOX_OUTPUT_ACCESSORS()
 
     LGetNameCache(const LAllocation &scopeObj) {
         setOperand(0, scopeObj);
     }
     const LAllocation *scopeObj() {
         return getOperand(0);
     }
     const MGetNameCache *mir() const {
         return mir_->toGetNameCache();
     }
 };
 
 class LCallGetIntrinsicValue : public LCallInstructionHelper<BOX_PIECES, 0, 0>
 {
   public:
-    LIR_HEADER(CallGetIntrinsicValue);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(CallGetIntrinsicValue)
+    BOX_OUTPUT_ACCESSORS()
 
     const MCallGetIntrinsicValue *mir() const {
         return mir_->toCallGetIntrinsicValue();
     }
 };
 
 // Patchable jump to stubs generated for a GetProperty cache, which loads a
 // boxed value.
 class LGetPropertyCacheV : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
-    LIR_HEADER(GetPropertyCacheV);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(GetPropertyCacheV)
+    BOX_OUTPUT_ACCESSORS()
 
     LGetPropertyCacheV(const LAllocation &object) {
         setOperand(0, object);
     }
     const MGetPropertyCache *mir() const {
         return mir_->toGetPropertyCache();
     }
 };
 
 // Patchable jump to stubs generated for a GetProperty cache, which loads a
 // value of a known type, possibly into an FP register.
 class LGetPropertyCacheT : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(GetPropertyCacheT);
+    LIR_HEADER(GetPropertyCacheT)
 
     LGetPropertyCacheT(const LAllocation &object) {
         setOperand(0, object);
     }
     const MGetPropertyCache *mir() const {
         return mir_->toGetPropertyCache();
     }
 };
 
 class LGetElementCacheV : public LInstructionHelper<BOX_PIECES, 1 + BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(GetElementCacheV);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(GetElementCacheV)
+    BOX_OUTPUT_ACCESSORS()
 
     static const size_t Index = 1;
 
     LGetElementCacheV(const LAllocation &object) {
         setOperand(0, object);
     }
     const LAllocation *object() {
         return getOperand(0);
@@ -2648,65 +2648,65 @@ class LGetElementCacheV : public LInstru
     const MGetElementCache *mir() const {
         return mir_->toGetElementCache();
     }
 };
 
 class LBindNameCache : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(BindNameCache);
+    LIR_HEADER(BindNameCache)
 
     LBindNameCache(const LAllocation &scopeChain) {
         setOperand(0, scopeChain);
     }
     const LAllocation *scopeChain() {
         return getOperand(0);
     }
     const MBindNameCache *mir() const {
         return mir_->toBindNameCache();
     }
 };
 
 // Load a value from an object's dslots or a slots vector.
 class LLoadSlotV : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
-    LIR_HEADER(LoadSlotV);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(LoadSlotV)
+    BOX_OUTPUT_ACCESSORS()
 
     LLoadSlotV(const LAllocation &in) {
         setOperand(0, in);
     }
     const MLoadSlot *mir() const {
         return mir_->toLoadSlot();
     }
 };
 
 // Load a typed value from an object's dslots or a slots vector. Unlike
 // LLoadSlotV, this can bypass extracting a type tag, directly retrieving a
 // pointer, integer, or double.
 class LLoadSlotT : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(LoadSlotT);
+    LIR_HEADER(LoadSlotT)
 
     LLoadSlotT(const LAllocation &in) {
         setOperand(0, in);
     }
     const MLoadSlot *mir() const {
         return mir_->toLoadSlot();
     }
 };
 
 // Store a value to an object's dslots or a slots vector.
 class LStoreSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(StoreSlotV);
+    LIR_HEADER(StoreSlotV)
 
     LStoreSlotV(const LAllocation &slots) {
         setOperand(0, slots);
     }
 
     static const size_t Value = 1;
 
     const MStoreSlot *mir() const {
@@ -2721,17 +2721,17 @@ class LStoreSlotV : public LInstructionH
 // few advantages over LStoreSlotV:
 // 1) We can bypass storing the type tag if the slot has the same type as
 //    the value.
 // 2) Better register allocation: we can store constants and FP regs directly
 //    without requiring a second register for the value.
 class LStoreSlotT : public LInstructionHelper<0, 2, 0>
 {
   public:
-    LIR_HEADER(StoreSlotT);
+    LIR_HEADER(StoreSlotT)
 
     LStoreSlotT(const LAllocation &slots, const LAllocation &value) {
         setOperand(0, slots);
         setOperand(1, value);
     }
     const MStoreSlot *mir() const {
         return mir_->toStoreSlot();
     }
@@ -2742,47 +2742,47 @@ class LStoreSlotT : public LInstructionH
         return getOperand(1);
     }
 };
 
 // Read length field of a JSString*.
 class LStringLength : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(StringLength);
+    LIR_HEADER(StringLength)
 
     LStringLength(const LAllocation &string) {
         setOperand(0, string);
     }
 
     const LAllocation *string() {
         return getOperand(0);
     }
 };
 
 // Take the floor of a number. Implements Math.floor().
 class LFloor : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(Floor);
+    LIR_HEADER(Floor)
 
     LFloor(const LAllocation &num) {
         setOperand(0, num);
     }
 
     MRound *mir() const {
         return mir_->toRound();
     }
 };
 
 // Round a number. Implements Math.round().
 class LRound : public LInstructionHelper<1, 1, 1>
 {
   public:
-    LIR_HEADER(Round);
+    LIR_HEADER(Round)
 
     LRound(const LAllocation &num, const LDefinition &temp) {
         setOperand(0, num);
         setTemp(0, temp);
     }
 
     const LDefinition *temp() {
         return getTemp(0);
@@ -2791,99 +2791,99 @@ class LRound : public LInstructionHelper
         return mir_->toRound();
     }
 };
 
 // Load a function's call environment.
 class LFunctionEnvironment : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(FunctionEnvironment);
+    LIR_HEADER(FunctionEnvironment)
 
     LFunctionEnvironment(const LAllocation &function) {
         setOperand(0, function);
     }
     const LAllocation *function() {
         return getOperand(0);
     }
 };
 
 class LCallGetProperty : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(CallGetProperty);
+    LIR_HEADER(CallGetProperty)
 
     static const size_t Value = 0;
 
     MCallGetProperty *mir() const {
         return mir_->toCallGetProperty();
     }
 };
 
 // Call js::GetElement.
 class LCallGetElement : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(CallGetElement);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(CallGetElement)
+    BOX_OUTPUT_ACCESSORS()
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
     MCallGetElement *mir() const {
         return mir_->toCallGetElement();
     }
 };
 
 // Call js::SetElement.
 class LCallSetElement : public LCallInstructionHelper<0, 1 + 2 * BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(CallSetElement);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(CallSetElement)
+    BOX_OUTPUT_ACCESSORS()
 
     static const size_t Index = 1;
     static const size_t Value = 1 + BOX_PIECES;
 };
 
 // Call a VM function to perform a property or name assignment of a generic value.
 class LCallSetProperty : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(CallSetProperty);
+    LIR_HEADER(CallSetProperty)
 
     LCallSetProperty(const LAllocation &obj) {
         setOperand(0, obj);
     }
 
     static const size_t Value = 1;
 
     const MCallSetProperty *mir() const {
         return mir_->toCallSetProperty();
     }
 };
 
 class LCallDeleteProperty : public LCallInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(CallDeleteProperty);
+    LIR_HEADER(CallDeleteProperty)
 
     static const size_t Value = 0;
 
     MDeleteProperty *mir() const {
         return mir_->toDeleteProperty();
     }
 };
 
 // Patchable jump to stubs generated for a SetProperty cache, which stores a
 // boxed value.
 class LSetPropertyCacheV : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
 {
   public:
-    LIR_HEADER(SetPropertyCacheV);
+    LIR_HEADER(SetPropertyCacheV)
 
     LSetPropertyCacheV(const LAllocation &object, const LDefinition &slots) {
         setOperand(0, object);
         setTemp(0, slots);
     }
 
     static const size_t Value = 1;
 
@@ -2894,17 +2894,17 @@ class LSetPropertyCacheV : public LInstr
 
 // Patchable jump to stubs generated for a SetProperty cache, which stores a
 // value of a known type.
 class LSetPropertyCacheT : public LInstructionHelper<0, 2, 1>
 {
     MIRType valueType_;
 
   public:
-    LIR_HEADER(SetPropertyCacheT);
+    LIR_HEADER(SetPropertyCacheT)
 
     LSetPropertyCacheT(const LAllocation &object, const LDefinition &slots,
                        const LAllocation &value, MIRType valueType)
         : valueType_(valueType)
     {
         setOperand(0, object);
         setOperand(1, value);
         setTemp(0, slots);
@@ -2916,33 +2916,33 @@ class LSetPropertyCacheT : public LInstr
     MIRType valueType() {
         return valueType_;
     }
 };
 
 class LCallIteratorStart : public LCallInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(CallIteratorStart);
+    LIR_HEADER(CallIteratorStart)
 
     LCallIteratorStart(const LAllocation &object) {
         setOperand(0, object);
     }
     const LAllocation *object() {
         return getOperand(0);
     }
     MIteratorStart *mir() const {
         return mir_->toIteratorStart();
     }
 };
 
 class LIteratorStart : public LInstructionHelper<1, 1, 3>
 {
   public:
-    LIR_HEADER(IteratorStart);
+    LIR_HEADER(IteratorStart)
 
     LIteratorStart(const LAllocation &object, const LDefinition &temp1,
                    const LDefinition &temp2, const LDefinition &temp3) {
         setOperand(0, object);
         setTemp(0, temp1);
         setTemp(1, temp2);
         setTemp(2, temp3);
     }
@@ -2961,18 +2961,18 @@ class LIteratorStart : public LInstructi
     MIteratorStart *mir() const {
         return mir_->toIteratorStart();
     }
 };
 
 class LIteratorNext : public LInstructionHelper<BOX_PIECES, 1, 1>
 {
   public:
-    LIR_HEADER(IteratorNext);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(IteratorNext)
+    BOX_OUTPUT_ACCESSORS()
 
     LIteratorNext(const LAllocation &iterator, const LDefinition &temp) {
         setOperand(0, iterator);
         setTemp(0, temp);
     }
     const LAllocation *object() {
         return getOperand(0);
     }
@@ -2982,17 +2982,17 @@ class LIteratorNext : public LInstructio
     MIteratorNext *mir() const {
         return mir_->toIteratorNext();
     }
 };
 
 class LIteratorMore : public LInstructionHelper<1, 1, 1>
 {
   public:
-    LIR_HEADER(IteratorMore);
+    LIR_HEADER(IteratorMore)
 
     LIteratorMore(const LAllocation &iterator, const LDefinition &temp) {
         setOperand(0, iterator);
         setTemp(0, temp);
     }
     const LAllocation *object() {
         return getOperand(0);
     }
@@ -3002,17 +3002,17 @@ class LIteratorMore : public LInstructio
     MIteratorMore *mir() const {
         return mir_->toIteratorMore();
     }
 };
 
 class LIteratorEnd : public LInstructionHelper<0, 1, 2>
 {
   public:
-    LIR_HEADER(IteratorEnd);
+    LIR_HEADER(IteratorEnd)
 
     LIteratorEnd(const LAllocation &iterator, const LDefinition &temp1,
                  const LDefinition &temp2) {
         setOperand(0, iterator);
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
     const LAllocation *object() {
@@ -3028,40 +3028,40 @@ class LIteratorEnd : public LInstruction
         return mir_->toIteratorEnd();
     }
 };
 
 // Read the number of actual arguments.
 class LArgumentsLength : public LInstructionHelper<1, 0, 0>
 {
   public:
-    LIR_HEADER(ArgumentsLength);
+    LIR_HEADER(ArgumentsLength)
 };
 
 // Load a value from the actual arguments.
 class LGetArgument : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
-    LIR_HEADER(GetArgument);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(GetArgument)
+    BOX_OUTPUT_ACCESSORS()
 
     LGetArgument(const LAllocation &index) {
         setOperand(0, index);
     }
     const LAllocation *index() {
         return getOperand(0);
     }
 };
 
 // Guard that a value is in a TypeSet.
 class LTypeBarrier : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 1>
 {
   public:
-    LIR_HEADER(TypeBarrier);
-    BOX_OUTPUT_ACCESSORS();
+    LIR_HEADER(TypeBarrier)
+    BOX_OUTPUT_ACCESSORS()
 
     LTypeBarrier(const LDefinition &temp) {
         setTemp(0, temp);
     }
 
     static const size_t Input = 0;
 
     const MTypeBarrier *mir() const {
@@ -3071,17 +3071,17 @@ class LTypeBarrier : public LInstruction
         return getTemp(0);
     }
 };
 
 // Guard that a value is in a TypeSet.
 class LMonitorTypes : public LInstructionHelper<0, BOX_PIECES, 1>
 {
   public:
-    LIR_HEADER(MonitorTypes);
+    LIR_HEADER(MonitorTypes)
 
     LMonitorTypes(const LDefinition &temp) {
         setTemp(0, temp);
     }
 
     static const size_t Input = 0;
 
     const MMonitorTypes *mir() const {
@@ -3091,17 +3091,17 @@ class LMonitorTypes : public LInstructio
         return getTemp(0);
     }
 };
 
 // Guard against an object's class.
 class LGuardClass : public LInstructionHelper<0, 1, 1>
 {
   public:
-    LIR_HEADER(GuardClass);
+    LIR_HEADER(GuardClass)
 
     LGuardClass(const LAllocation &in, const LDefinition &temp) {
         setOperand(0, in);
         setTemp(0, temp);
     }
     const MGuardClass *mir() const {
         return mir_->toGuardClass();
     }
@@ -3122,17 +3122,17 @@ class LPhi : public LInstruction
     LAllocation *inputs_;
     LDefinition def_;
 
     bool init(MIRGenerator *gen);
 
     LPhi(MPhi *mir);
 
   public:
-    LIR_HEADER(Phi);
+    LIR_HEADER(Phi)
 
     static LPhi *New(MIRGenerator *gen, MPhi *phi);
 
     size_t numDefs() const {
         return 1;
     }
     LDefinition *getDef(size_t index) {
         JS_ASSERT(index == 0);
@@ -3167,17 +3167,17 @@ class LPhi : public LInstruction
     virtual void printInfo(FILE *fp) {
         printOperands(fp);
     }
 };
 
 class LIn : public LCallInstructionHelper<1, BOX_PIECES+1, 0>
 {
   public:
-    LIR_HEADER(In);
+    LIR_HEADER(In)
     LIn(const LAllocation &rhs) {
         setOperand(RHS, rhs);
     }
 
     const LAllocation *lhs() {
         return getOperand(LHS);
     }
     const LAllocation *rhs() {
@@ -3186,34 +3186,34 @@ class LIn : public LCallInstructionHelpe
 
     static const size_t LHS = 0;
     static const size_t RHS = BOX_PIECES;
 };
 
 class LInstanceOfO : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LIR_HEADER(InstanceOfO);
+    LIR_HEADER(InstanceOfO)
     LInstanceOfO(const LAllocation &lhs) {
         setOperand(0, lhs);
     }
 
     MInstanceOf *mir() const {
         return mir_->toInstanceOf();
     }
 
     const LAllocation *lhs() {
         return getOperand(0);
     }
 };
 
 class LInstanceOfV : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(InstanceOfV);
+    LIR_HEADER(InstanceOfV)
     LInstanceOfV() {
     }
 
     MInstanceOf *mir() const {
         return mir_->toInstanceOf();
     }
 
     const LAllocation *lhs() {
@@ -3221,17 +3221,17 @@ class LInstanceOfV : public LInstruction
     }
 
     static const size_t LHS = 0;
 };
 
 class LCallInstanceOf : public LCallInstructionHelper<1, BOX_PIECES+1, 0>
 {
   public:
-    LIR_HEADER(CallInstanceOf);
+    LIR_HEADER(CallInstanceOf)
     LCallInstanceOf(const LAllocation &rhs) {
         setOperand(RHS, rhs);
     }
 
     const LDefinition *output() {
         return this->getDef(0);
     }
     const LAllocation *lhs() {
@@ -3243,17 +3243,17 @@ class LCallInstanceOf : public LCallInst
 
     static const size_t LHS = 0;
     static const size_t RHS = BOX_PIECES;
 };
 
 class LFunctionBoundary : public LInstructionHelper<0, 0, 1>
 {
   public:
-    LIR_HEADER(FunctionBoundary);
+    LIR_HEADER(FunctionBoundary)
 
     LFunctionBoundary(const LDefinition &temp) {
         setTemp(0, temp);
     }
 
     const LDefinition *temp() {
         return getTemp(0);
     }
--- a/js/src/ion/LIR.h
+++ b/js/src/ion/LIR.h
@@ -619,17 +619,17 @@ class LInstruction
     // Returns information about temporary registers needed. Each temporary
     // register is an LUse with a TEMPORARY policy, or a fixed register.
     virtual size_t numTemps() const = 0;
     virtual LDefinition *getTemp(size_t index) = 0;
     virtual void setTemp(size_t index, const LDefinition &a) = 0;
 
     virtual bool isCall() const {
         return false;
-    };
+    }
     uint32_t id() const {
         return id_;
     }
     void setId(uint32_t id) {
         JS_ASSERT(!id_);
         JS_ASSERT(id);
         id_ = id;
     }
--- a/js/src/ion/LinearScan.h
+++ b/js/src/ion/LinearScan.h
@@ -120,18 +120,18 @@ class LinearScanAllocator : public LiveR
     size_t findFirstSafepoint(LiveInterval *interval, size_t firstSafepoint);
     size_t findFirstNonCallSafepoint(CodePosition from);
     bool isSpilledAt(LiveInterval *interval, CodePosition pos);
 
 #ifdef DEBUG
     void validateIntervals();
     void validateAllocations();
 #else
-    inline void validateIntervals() { };
-    inline void validateAllocations() { };
+    inline void validateIntervals() { }
+    inline void validateAllocations() { }
 #endif
 
 #ifdef JS_NUNBOX32
     LinearScanVirtualRegister *otherHalfOfNunbox(VirtualRegister *vreg);
 #endif
 
   public:
     LinearScanAllocator(MIRGenerator *mir, LIRGenerator *lir, LIRGraph &graph)
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -1483,19 +1483,23 @@ LIRGenerator::visitLoadElement(MLoadElem
         return defineBox(lir, ins);
       }
       case MIRType_Undefined:
       case MIRType_Null:
         JS_ASSERT(!"typed load must have a payload");
         return false;
 
       default:
-        JS_ASSERT(!ins->fallible());
-        return define(new LLoadElementT(useRegister(ins->elements()),
-                                        useRegisterOrConstant(ins->index())), ins);
+      {
+        LLoadElementT *lir = new LLoadElementT(useRegister(ins->elements()),
+                                               useRegisterOrConstant(ins->index()));
+        if (ins->fallible() && !assignSnapshot(lir))
+            return false;
+        return define(lir, ins);
+      }
     }
 }
 
 bool
 LIRGenerator::visitLoadElementHole(MLoadElementHole *ins)
 {
     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
     JS_ASSERT(ins->index()->type() == MIRType_Int32);
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -566,17 +566,17 @@ class MStart : public MNullaryInstructio
     StartType startType_;
 
   private:
     MStart(StartType startType)
       : startType_(startType)
     { }
 
   public:
-    INSTRUCTION_HEADER(Start);
+    INSTRUCTION_HEADER(Start)
     static MStart *New(StartType startType) {
         return new MStart(startType);
     }
 
     StartType startType() {
         return startType_;
     }
 };
@@ -587,32 +587,32 @@ class MStart : public MNullaryInstructio
 class MOsrEntry : public MNullaryInstruction
 {
   protected:
     MOsrEntry() {
         setResultType(MIRType_StackFrame);
     }
 
   public:
-    INSTRUCTION_HEADER(OsrEntry);
+    INSTRUCTION_HEADER(OsrEntry)
     static MOsrEntry *New() {
         return new MOsrEntry;
     }
 };
 
 // No-op instruction. This cannot be moved or eliminated, and is intended for
 // anchoring resume points at arbitrary points in a block.
 class MNop : public MNullaryInstruction
 {
   protected:
     MNop() {
     }
 
   public:
-    INSTRUCTION_HEADER(Nop);
+    INSTRUCTION_HEADER(Nop)
     static MNop *New() {
         return new MNop();
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
@@ -621,17 +621,17 @@ class MNop : public MNullaryInstruction
 class MConstant : public MNullaryInstruction
 {
     Value value_;
 
   protected:
     MConstant(const Value &v);
 
   public:
-    INSTRUCTION_HEADER(Constant);
+    INSTRUCTION_HEADER(Constant)
     static MConstant *New(const Value &v);
 
     const js::Value &value() const {
         return value_;
     }
     const js::Value *vp() const {
         return &value_;
     }
@@ -659,17 +659,17 @@ class MParameter : public MNullaryInstru
     MParameter(int32_t index, const types::TypeSet *types)
       : index_(index),
         typeSet_(types)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(Parameter);
+    INSTRUCTION_HEADER(Parameter)
     static MParameter *New(int32_t index, const types::TypeSet *types);
 
     int32_t index() const {
         return index_;
     }
     const types::TypeSet *typeSet() const {
         return typeSet_;
     }
@@ -683,17 +683,17 @@ class MCallee : public MNullaryInstructi
 {
   public:
     MCallee()
     {
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(Callee);
+    INSTRUCTION_HEADER(Callee)
 
     bool congruentTo(MDefinition * const &ins) const {
         return congruentIfOperandsEqual(ins);
     }
 
     static MCallee *New() {
         return new MCallee();
     }
@@ -743,17 +743,17 @@ class MTableSwitch
 
   protected:
     void setOperand(size_t index, MDefinition *operand) {
         JS_ASSERT(index == 0);
         operand_ = operand;
     }
 
   public:
-    INSTRUCTION_HEADER(TableSwitch);
+    INSTRUCTION_HEADER(TableSwitch)
     static MTableSwitch *New(MDefinition *ins,
                              int32_t low, int32_t high);
 
     size_t numSuccessors() const {
         return successors_.length();
     }
 
     MBasicBlock *getSuccessor(size_t i) const {
@@ -859,17 +859,17 @@ class MAryControlInstruction : public MC
 // Jump to the start of another basic block.
 class MGoto : public MAryControlInstruction<0, 1>
 {
     MGoto(MBasicBlock *target) {
         setSuccessor(0, target);
     }
 
   public:
-    INSTRUCTION_HEADER(Goto);
+    INSTRUCTION_HEADER(Goto)
     static MGoto *New(MBasicBlock *target);
 
     MBasicBlock *target() {
         return getSuccessor(0);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
@@ -894,17 +894,17 @@ class MTest
 {
     MTest(MDefinition *ins, MBasicBlock *if_true, MBasicBlock *if_false) {
         initOperand(0, ins);
         setSuccessor(0, if_true);
         setSuccessor(1, if_false);
     }
 
   public:
-    INSTRUCTION_HEADER(Test);
+    INSTRUCTION_HEADER(Test)
     static MTest *New(MDefinition *ins,
                       MBasicBlock *ifTrue, MBasicBlock *ifFalse);
 
     MBasicBlock *ifTrue() const {
         return getSuccessor(0);
     }
     MBasicBlock *ifFalse() const {
         return getSuccessor(1);
@@ -927,17 +927,17 @@ class MReturn
   : public MAryControlInstruction<1, 0>,
     public BoxInputsPolicy
 {
     MReturn(MDefinition *ins) {
         initOperand(0, ins);
     }
 
   public:
-    INSTRUCTION_HEADER(Return);
+    INSTRUCTION_HEADER(Return)
     static MReturn *New(MDefinition *ins) {
         return new MReturn(ins);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
     AliasSet getAliasSet() const {
@@ -949,17 +949,17 @@ class MThrow
   : public MAryControlInstruction<1, 0>,
     public BoxInputsPolicy
 {
     MThrow(MDefinition *ins) {
         initOperand(0, ins);
     }
 
   public:
-    INSTRUCTION_HEADER(Throw);
+    INSTRUCTION_HEADER(Throw)
     static MThrow *New(MDefinition *ins) {
         return new MThrow(ins);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
     virtual AliasSet getAliasSet() const {
@@ -979,17 +979,17 @@ class MNewArray : public MNullaryInstruc
     // Number of space to allocate for the array.
     uint32_t count_;
     // Template for the created object.
     CompilerRootObject templateObject_;
     // Allocate space at initialization or not
     AllocatingBehaviour allocating_;
 
   public:
-    INSTRUCTION_HEADER(NewArray);
+    INSTRUCTION_HEADER(NewArray)
 
     MNewArray(uint32_t count, JSObject *templateObject, AllocatingBehaviour allocating)
       : count_(count),
         templateObject_(templateObject),
         allocating_(allocating)
     {
         setResultType(MIRType_Object);
     }
@@ -1023,17 +1023,17 @@ class MNewObject : public MNullaryInstru
 
     MNewObject(JSObject *templateObject)
       : templateObject_(templateObject)
     {
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(NewObject);
+    INSTRUCTION_HEADER(NewObject)
 
     static MNewObject *New(JSObject *templateObject) {
         return new MNewObject(templateObject);
     }
 
     JSObject *templateObject() const {
         return templateObject_;
     }
@@ -1052,17 +1052,17 @@ class MInitProp
       : name_(name)
     {
         initOperand(0, obj);
         initOperand(1, value);
         setResultType(MIRType_None);
     }
 
   public:
-    INSTRUCTION_HEADER(InitProp);
+    INSTRUCTION_HEADER(InitProp)
 
     static MInitProp *New(MDefinition *obj, HandlePropertyName name, MDefinition *value) {
         return new MInitProp(obj, name, value);
     }
 
     MDefinition *getObject() const {
         return getOperand(0);
     }
@@ -1079,17 +1079,17 @@ class MInitProp
 };
 
 // Designates the start of call frame construction.
 // Generates code to adjust the stack pointer for the argument vector.
 // Argc is inferred by checking the use chain during lowering.
 class MPrepareCall : public MNullaryInstruction
 {
   public:
-    INSTRUCTION_HEADER(PrepareCall);
+    INSTRUCTION_HEADER(PrepareCall)
 
     MPrepareCall()
     { }
 
     // Get the vector size for the upcoming call by looking at the call.
     uint32_t argc() const;
 
     AliasSet getAliasSet() const {
@@ -1142,17 +1142,17 @@ class MCall
       : construct_(construct),
         target_(target),
         numActualArgs_(numActualArgs)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(Call);
+    INSTRUCTION_HEADER(Call)
     static MCall *New(JSFunction *target, size_t maxArgc, size_t numActualArgs, bool construct);
 
     void initPrepareCall(MDefinition *start) {
         JS_ASSERT(start->isPrepareCall());
         return initOperand(PrepareCallOperandIndex, start);
     }
     void initFunction(MDefinition *func) {
         JS_ASSERT(!func->isPassArg());
@@ -1216,17 +1216,17 @@ class MApplyArgs
     {
         initOperand(0, fun);
         initOperand(1, argc);
         initOperand(2, self);
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(ApplyArgs);
+    INSTRUCTION_HEADER(ApplyArgs)
     static MApplyArgs *New(JSFunction *target, MDefinition *fun, MDefinition *argc,
                            MDefinition *self);
 
     MDefinition *getFunction() const {
         return getOperand(0);
     }
 
     // For TI-informed monomorphic callsites.
@@ -1374,17 +1374,17 @@ class MCompare
       : MBinaryInstruction(left, right),
         jsop_(jsop)
     {
         setResultType(MIRType_Boolean);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(Compare);
+    INSTRUCTION_HEADER(Compare)
     static MCompare *New(MDefinition *left, MDefinition *right, JSOp op);
 
     bool tryFold(bool *result);
     bool evaluateConstantOperands(bool *result);
     MDefinition *foldsTo(bool useValueNumbers);
 
     void infer(JSContext *cx, const TypeOracle::BinaryTypes &b);
     MIRType specialization() const {
@@ -1421,17 +1421,17 @@ class MBox : public MUnaryInstruction
     MBox(MDefinition *ins)
       : MUnaryInstruction(ins)
     {
         setResultType(MIRType_Value);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(Box);
+    INSTRUCTION_HEADER(Box)
     static MBox *New(MDefinition *ins)
     {
         // Cannot box a box.
         JS_ASSERT(ins->type() != MIRType_Value);
 
         return new MBox(ins);
     }
     bool congruentTo(MDefinition *const &ins) const {
@@ -1474,17 +1474,17 @@ class MUnbox : public MUnaryInstruction
 
         if (mode_ == TypeBarrier || mode_ == TypeGuard)
             setGuard();
         if (mode_ == TypeGuard)
             mode_ = Fallible;
     }
 
   public:
-    INSTRUCTION_HEADER(Unbox);
+    INSTRUCTION_HEADER(Unbox)
     static MUnbox *New(MDefinition *ins, MIRType type, Mode mode)
     {
         return new MUnbox(ins, type, mode);
     }
 
     Mode mode() const {
         return mode_;
     }
@@ -1515,17 +1515,17 @@ class MGuardObject : public MUnaryInstru
       : MUnaryInstruction(ins)
     {
         setGuard();
         setMovable();
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(GuardObject);
+    INSTRUCTION_HEADER(GuardObject)
 
     static MGuardObject *New(MDefinition *ins) {
         return new MGuardObject(ins);
     }
 
     MDefinition *input() const {
         return getOperand(0);
     }
@@ -1546,17 +1546,17 @@ class MGuardString
       : MUnaryInstruction(ins)
     {
         setGuard();
         setMovable();
         setResultType(MIRType_String);
     }
 
   public:
-    INSTRUCTION_HEADER(GuardString);
+    INSTRUCTION_HEADER(GuardString)
 
     static MGuardString *New(MDefinition *ins) {
         return new MGuardString(ins);
     }
 
     MDefinition *input() const {
         return getOperand(0);
     }
@@ -1583,17 +1583,17 @@ class MCreateThis
       : templateObject_(templateObject)
     {
         initOperand(0, callee);
         initOperand(1, prototype);
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(CreateThis);
+    INSTRUCTION_HEADER(CreateThis)
     static MCreateThis *New(MDefinition *callee, MDefinition *prototype, JSObject *templateObject)
     {
         return new MCreateThis(callee, prototype, templateObject);
     }
 
     MDefinition *getCallee() const {
         return getOperand(0);
     }
@@ -1627,17 +1627,17 @@ class MReturnFromCtor
 {
     MReturnFromCtor(MDefinition *value, MDefinition *object) {
         initOperand(0, value);
         initOperand(1, object);
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(ReturnFromCtor);
+    INSTRUCTION_HEADER(ReturnFromCtor)
     static MReturnFromCtor *New(MDefinition *value, MDefinition *object)
     {
         return new MReturnFromCtor(value, object);
     }
 
     MDefinition *getValue() const {
         return getOperand(0);
     }
@@ -1665,17 +1665,17 @@ class MPassArg : public MUnaryInstructio
   private:
     MPassArg(MDefinition *def)
       : MUnaryInstruction(def), argnum_(-1)
     {
         setResultType(def->type());
     }
 
   public:
-    INSTRUCTION_HEADER(PassArg);
+    INSTRUCTION_HEADER(PassArg)
     static MPassArg *New(MDefinition *def)
     {
         return new MPassArg(def);
     }
 
     MDefinition *getArgument() const {
         return getOperand(0);
     }
@@ -1702,17 +1702,17 @@ class MToDouble
     MToDouble(MDefinition *def)
       : MUnaryInstruction(def)
     {
         setResultType(MIRType_Double);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(ToDouble);
+    INSTRUCTION_HEADER(ToDouble)
     static MToDouble *New(MDefinition *def)
     {
         return new MToDouble(def);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
     MDefinition *input() const {
         return getOperand(0);
@@ -1736,17 +1736,17 @@ class MToInt32 : public MUnaryInstructio
       : MUnaryInstruction(def),
         canBeNegativeZero_(true)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(ToInt32);
+    INSTRUCTION_HEADER(ToInt32)
     static MToInt32 *New(MDefinition *def)
     {
         return new MToInt32(def);
     }
 
     MDefinition *input() const {
         return getOperand(0);
     }
@@ -1779,17 +1779,17 @@ class MTruncateToInt32 : public MUnaryIn
     MTruncateToInt32(MDefinition *def)
       : MUnaryInstruction(def)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(TruncateToInt32);
+    INSTRUCTION_HEADER(TruncateToInt32)
     static MTruncateToInt32 *New(MDefinition *def)
     {
         return new MTruncateToInt32(def);
     }
 
     MDefinition *input() const {
         return getOperand(0);
     }
@@ -1810,17 +1810,17 @@ class MToString : public MUnaryInstructi
     MToString(MDefinition *def)
       : MUnaryInstruction(def)
     {
         setResultType(MIRType_String);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(ToString);
+    INSTRUCTION_HEADER(ToString)
     static MToString *New(MDefinition *def)
     {
         return new MToString(def);
     }
 
     MDefinition *input() const {
         return getOperand(0);
     }
@@ -1844,17 +1844,17 @@ class MBitNot
     MBitNot(MDefinition *input)
       : MUnaryInstruction(input)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(BitNot);
+    INSTRUCTION_HEADER(BitNot)
     static MBitNot *New(MDefinition *input);
 
     TypePolicy *typePolicy() {
         return this;
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
     void infer(const TypeOracle::UnaryTypes &u);
@@ -1878,17 +1878,17 @@ class MTypeOf
     MTypeOf(MDefinition *def, MIRType inputType)
       : MUnaryInstruction(def), inputType_(inputType)
     {
         setResultType(MIRType_String);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(TypeOf);
+    INSTRUCTION_HEADER(TypeOf)
 
     static MTypeOf *New(MDefinition *def, MIRType inputType) {
         return new MTypeOf(def, inputType);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -1915,17 +1915,17 @@ class MToId
 {
     MToId(MDefinition *object, MDefinition *index)
       : MBinaryInstruction(object, index)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(ToId);
+    INSTRUCTION_HEADER(ToId)
 
     static MToId *New(MDefinition *object, MDefinition *index) {
         return new MToId(object, index);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -1966,17 +1966,17 @@ class MBinaryBitwiseInstruction
 
 class MBitAnd : public MBinaryBitwiseInstruction
 {
     MBitAnd(MDefinition *left, MDefinition *right)
       : MBinaryBitwiseInstruction(left, right)
     { }
 
   public:
-    INSTRUCTION_HEADER(BitAnd);
+    INSTRUCTION_HEADER(BitAnd)
     static MBitAnd *New(MDefinition *left, MDefinition *right);
 
     MDefinition *foldIfZero(size_t operand) {
         return getOperand(operand); // 0 & x => 0;
     }
     MDefinition *foldIfNegOne(size_t operand) {
         return getOperand(1 - operand); // x & -1 => x
     }
@@ -1988,17 +1988,17 @@ class MBitAnd : public MBinaryBitwiseIns
 
 class MBitOr : public MBinaryBitwiseInstruction
 {
     MBitOr(MDefinition *left, MDefinition *right)
       : MBinaryBitwiseInstruction(left, right)
     { }
 
   public:
-    INSTRUCTION_HEADER(BitOr);
+    INSTRUCTION_HEADER(BitOr)
     static MBitOr *New(MDefinition *left, MDefinition *right);
 
     MDefinition *foldIfZero(size_t operand) {
         return getOperand(1 - operand); // 0 | x => x, so if ith is 0, return (1-i)th
     }
     MDefinition *foldIfNegOne(size_t operand) {
         return getOperand(operand); // x | -1 => -1
     }
@@ -2009,17 +2009,17 @@ class MBitOr : public MBinaryBitwiseInst
 
 class MBitXor : public MBinaryBitwiseInstruction
 {
     MBitXor(MDefinition *left, MDefinition *right)
       : MBinaryBitwiseInstruction(left, right)
     { }
 
   public:
-    INSTRUCTION_HEADER(BitXor);
+    INSTRUCTION_HEADER(BitXor)
     static MBitXor *New(MDefinition *left, MDefinition *right);
 
     MDefinition *foldIfZero(size_t operand) {
         return getOperand(1 - operand); // 0 ^ x => x
     }
     MDefinition *foldIfNegOne(size_t operand) {
         return this;
     }
@@ -2048,17 +2048,17 @@ class MShiftInstruction
 
 class MLsh : public MShiftInstruction
 {
     MLsh(MDefinition *left, MDefinition *right)
       : MShiftInstruction(left, right)
     { }
 
   public:
-    INSTRUCTION_HEADER(Lsh);
+    INSTRUCTION_HEADER(Lsh)
     static MLsh *New(MDefinition *left, MDefinition *right);
 
     MDefinition *foldIfZero(size_t operand) {
         // 0 << x => 0
         // x << 0 => x
         return getOperand(0);
     }
 
@@ -2067,17 +2067,17 @@ class MLsh : public MShiftInstruction
 
 class MRsh : public MShiftInstruction
 {
     MRsh(MDefinition *left, MDefinition *right)
       : MShiftInstruction(left, right)
     { }
 
   public:
-    INSTRUCTION_HEADER(Rsh);
+    INSTRUCTION_HEADER(Rsh)
     static MRsh *New(MDefinition *left, MDefinition *right);
 
     MDefinition *foldIfZero(size_t operand) {
         // 0 >> x => 0
         // x >> 0 => x
         return getOperand(0);
     }
     void computeRange();
@@ -2088,17 +2088,17 @@ class MUrsh : public MShiftInstruction
     bool canOverflow_;
 
     MUrsh(MDefinition *left, MDefinition *right)
       : MShiftInstruction(left, right),
         canOverflow_(true)
     { }
 
   public:
-    INSTRUCTION_HEADER(Ursh);
+    INSTRUCTION_HEADER(Ursh)
     static MUrsh *New(MDefinition *left, MDefinition *right);
 
     MDefinition *foldIfZero(size_t operand) {
         // 0 >>> x => 0
         if (operand == 0)
             return getOperand(0);
 
         return this;
@@ -2182,17 +2182,17 @@ class MMinMax
     {
         JS_ASSERT(type == MIRType_Double || type == MIRType_Int32);
         setResultType(type);
         setMovable();
         specialization_ = type;
     }
 
   public:
-    INSTRUCTION_HEADER(MinMax);
+    INSTRUCTION_HEADER(MinMax)
     static MMinMax *New(MDefinition *left, MDefinition *right, MIRType type, bool isMax) {
         return new MMinMax(left, right, type, isMax);
     }
 
     bool isMax() const {
         return isMax_;
     }
     MIRType specialization() const {
@@ -2224,17 +2224,17 @@ class MAbs
     {
         JS_ASSERT(type == MIRType_Double || type == MIRType_Int32);
         setResultType(type);
         setMovable();
         specialization_ = type;
     }
 
   public:
-    INSTRUCTION_HEADER(Abs);
+    INSTRUCTION_HEADER(Abs)
     static MAbs *New(MDefinition *num, MIRType type) {
         return new MAbs(num, type);
     }
     MDefinition *num() const {
         return getOperand(0);
     }
     TypePolicy *typePolicy() {
         return this;
@@ -2257,17 +2257,17 @@ class MSqrt
     MSqrt(MDefinition *num)
       : MUnaryInstruction(num)
     {
         setResultType(MIRType_Double);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(Sqrt);
+    INSTRUCTION_HEADER(Sqrt)
     static MSqrt *New(MDefinition *num) {
         return new MSqrt(num);
     }
     MDefinition *num() const {
         return getOperand(0);
     }
     TypePolicy *typePolicy() {
         return this;
@@ -2290,17 +2290,17 @@ class MPow
       : MBinaryInstruction(input, power),
         PowPolicy(powerType)
     {
         setResultType(MIRType_Double);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(Pow);
+    INSTRUCTION_HEADER(Pow)
     static MPow *New(MDefinition *input, MDefinition *power, MIRType powerType) {
         return new MPow(input, power, powerType);
     }
 
     MDefinition *input() const {
         return lhs();
     }
     MDefinition *power() const {
@@ -2325,17 +2325,17 @@ class MPowHalf
     MPowHalf(MDefinition *input)
       : MUnaryInstruction(input)
     {
         setResultType(MIRType_Double);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(PowHalf);
+    INSTRUCTION_HEADER(PowHalf)
     static MPowHalf *New(MDefinition *input) {
         return new MPowHalf(input);
     }
     MDefinition *input() const {
         return getOperand(0);
     }
     bool congruentTo(MDefinition *const &ins) const {
         return congruentIfOperandsEqual(ins);
@@ -2352,21 +2352,21 @@ class MPowHalf
 class MRandom : public MNullaryInstruction
 {
     MRandom()
     {
         setResultType(MIRType_Double);
     }
 
   public:
-    INSTRUCTION_HEADER(Random);
+    INSTRUCTION_HEADER(Random)
     static MRandom *New() {
         return new MRandom;
     }
-    
+
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 class MMathFunction
   : public MUnaryInstruction,
     public DoublePolicy<0>
@@ -2386,17 +2386,17 @@ class MMathFunction
     MMathFunction(MDefinition *input, Function function, MathCache *cache)
       : MUnaryInstruction(input), function_(function), cache_(cache)
     {
         setResultType(MIRType_Double);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(MathFunction);
+    INSTRUCTION_HEADER(MathFunction)
     static MMathFunction *New(MDefinition *input, Function function, MathCache *cache) {
         return new MMathFunction(input, function, cache);
     }
     Function function() const {
         return function_;
     }
     MathCache *cache() const {
         return cache_;
@@ -2427,17 +2427,17 @@ class MAdd : public MBinaryArithInstruct
     MAdd(MDefinition *left, MDefinition *right)
       : MBinaryArithInstruction(left, right),
         implicitTruncate_(false)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(Add);
+    INSTRUCTION_HEADER(Add)
     static MAdd *New(MDefinition *left, MDefinition *right) {
         return new MAdd(left, right);
     }
     void analyzeTruncateBackward();
 
     bool isTruncated() const {
         return implicitTruncate_;
     }
@@ -2459,17 +2459,17 @@ class MSub : public MBinaryArithInstruct
     MSub(MDefinition *left, MDefinition *right)
       : MBinaryArithInstruction(left, right),
         implicitTruncate_(false)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(Sub);
+    INSTRUCTION_HEADER(Sub)
     static MSub *New(MDefinition *left, MDefinition *right) {
         return new MSub(left, right);
     }
 
     void analyzeTruncateBackward();
     bool isTruncated() const {
         return implicitTruncate_;
     }
@@ -2508,17 +2508,17 @@ class MMul : public MBinaryArithInstruct
         implicitTruncate_(false)
     {
         if (type != MIRType_Value)
             specialization_ = type;
         setResultType(type);
     }
 
   public:
-    INSTRUCTION_HEADER(Mul);
+    INSTRUCTION_HEADER(Mul)
     static MMul *New(MDefinition *left, MDefinition *right) {
         return new MMul(left, right, MIRType_Value);
     }
     static MMul *New(MDefinition *left, MDefinition *right, MIRType type) {
         return new MMul(left, right, type);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
@@ -2579,17 +2579,17 @@ class MDiv : public MBinaryArithInstruct
     {
         if (type != MIRType_Value)
             specialization_ = type;
         setResultType(type);
     }
 
 
   public:
-    INSTRUCTION_HEADER(Div);
+    INSTRUCTION_HEADER(Div)
     static MDiv *New(MDefinition *left, MDefinition *right) {
         return new MDiv(left, right, MIRType_Value);
     }
     static MDiv *New(MDefinition *left, MDefinition *right, MIRType type) {
         return new MDiv(left, right, type);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
@@ -2631,17 +2631,17 @@ class MMod : public MBinaryArithInstruct
 {
     MMod(MDefinition *left, MDefinition *right)
       : MBinaryArithInstruction(left, right)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(Mod);
+    INSTRUCTION_HEADER(Mod)
     static MMod *New(MDefinition *left, MDefinition *right) {
         return new MMod(left, right);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
     double getIdentity() {
         JS_NOT_REACHED("not used");
         return 1;
@@ -2657,17 +2657,17 @@ class MConcat
     MConcat(MDefinition *left, MDefinition *right)
       : MBinaryInstruction(left, right)
     {
         setMovable();
         setResultType(MIRType_String);
     }
 
   public:
-    INSTRUCTION_HEADER(Concat);
+    INSTRUCTION_HEADER(Concat)
     static MConcat *New(MDefinition *left, MDefinition *right) {
         return new MConcat(left, right);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
     bool congruentTo(MDefinition *const &ins) const {
@@ -2685,17 +2685,17 @@ class MCharCodeAt
     MCharCodeAt(MDefinition *str, MDefinition *index)
         : MBinaryInstruction(str, index)
     {
         setMovable();
         setResultType(MIRType_Int32);
     }
 
   public:
-    INSTRUCTION_HEADER(CharCodeAt);
+    INSTRUCTION_HEADER(CharCodeAt)
 
     static MCharCodeAt *New(MDefinition *str, MDefinition *index) {
         return new MCharCodeAt(str, index);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -2715,17 +2715,17 @@ class MFromCharCode
     MFromCharCode(MDefinition *code)
       : MUnaryInstruction(code)
     {
         setMovable();
         setResultType(MIRType_String);
     }
 
   public:
-    INSTRUCTION_HEADER(FromCharCode);
+    INSTRUCTION_HEADER(FromCharCode)
 
     static MFromCharCode *New(MDefinition *code) {
         return new MFromCharCode(code);
     }
 
     virtual AliasSet getAliasSet() const {
         return AliasSet::None();
     }
@@ -2748,17 +2748,17 @@ class MPhi : public MDefinition, public 
     }
 
   protected:
     void setOperand(size_t index, MDefinition *operand) {
         inputs_[index] = operand;
     }
 
   public:
-    INSTRUCTION_HEADER(Phi);
+    INSTRUCTION_HEADER(Phi)
     static MPhi *New(uint32_t slot);
 
     MDefinition *getOperand(size_t index) const {
         return inputs_[index];
     }
     size_t numOperands() const {
         return inputs_.length();
     }
@@ -2808,17 +2808,17 @@ class MBeta : public MUnaryInstruction
         : MUnaryInstruction(val),
           comparison_(comp),
           val_(val)
     {
         setResultType(val->type());
     }
 
   public:
-    INSTRUCTION_HEADER(Beta);
+    INSTRUCTION_HEADER(Beta)
     void printOpcode(FILE *fp);
     static MBeta *New(MDefinition *val, const Range *comp)
     {
         return new MBeta(val, comp);
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
@@ -2837,17 +2837,17 @@ class MOsrValue : public MUnaryInstructi
     MOsrValue(MOsrEntry *entry, ptrdiff_t frameOffset)
       : MUnaryInstruction(entry),
         frameOffset_(frameOffset)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(OsrValue);
+    INSTRUCTION_HEADER(OsrValue)
     static MOsrValue *New(MOsrEntry *entry, ptrdiff_t frameOffset) {
         return new MOsrValue(entry, frameOffset);
     }
 
     ptrdiff_t frameOffset() const {
         return frameOffset_;
     }
 
@@ -2867,47 +2867,47 @@ class MOsrScopeChain : public MUnaryInst
   private:
     MOsrScopeChain(MOsrEntry *entry)
       : MUnaryInstruction(entry)
     {
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(OsrScopeChain);
+    INSTRUCTION_HEADER(OsrScopeChain)
     static MOsrScopeChain *New(MOsrEntry *entry) {
         return new MOsrScopeChain(entry);
     }
 
     MOsrEntry *entry() {
         return getOperand(0)->toOsrEntry();
     }
 };
 
 // Check the current frame for over-recursion past the global stack limit.
 class MCheckOverRecursed : public MNullaryInstruction
 {
   public:
-    INSTRUCTION_HEADER(CheckOverRecursed);
+    INSTRUCTION_HEADER(CheckOverRecursed)
 };
 
 // Check the script's use count and trigger recompilation to inline
 // calls when the script becomes hot.
 class MRecompileCheck : public MNullaryInstruction
 {
     uint32_t minUses_;
 
     MRecompileCheck(uint32_t minUses)
       : minUses_(minUses)
     {
         setGuard();
     }
 
   public:
-    INSTRUCTION_HEADER(RecompileCheck);
+    INSTRUCTION_HEADER(RecompileCheck)
 
     uint32_t minUses() const {
         return minUses_;
     }
     static MRecompileCheck *New(uint32_t minUses) {
         return new MRecompileCheck(minUses);
     }
     AliasSet getAliasSet() const {
@@ -2918,17 +2918,17 @@ class MRecompileCheck : public MNullaryI
 // Check whether we need to fire the interrupt handler.
 class MInterruptCheck : public MNullaryInstruction
 {
     MInterruptCheck() {
         setGuard();
     }
 
   public:
-    INSTRUCTION_HEADER(InterruptCheck);
+    INSTRUCTION_HEADER(InterruptCheck)
 
     static MInterruptCheck *New() {
         return new MInterruptCheck();
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
@@ -2943,17 +2943,17 @@ class MDefVar : public MUnaryInstruction
     MDefVar(PropertyName *name, unsigned attrs, MDefinition *scopeChain)
       : MUnaryInstruction(scopeChain),
         name_(name),
         attrs_(attrs)
     {
     }
 
   public:
-    INSTRUCTION_HEADER(DefVar);
+    INSTRUCTION_HEADER(DefVar)
 
     static MDefVar *New(PropertyName *name, unsigned attrs, MDefinition *scopeChain) {
         return new MDefVar(name, attrs, scopeChain);
     }
 
     PropertyName *name() const {
         return name_;
     }
@@ -3056,17 +3056,17 @@ class MLambda
 
     MLambda(MDefinition *scopeChain, JSFunction *fun)
       : MUnaryInstruction(scopeChain), fun_(fun)
     {
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(Lambda);
+    INSTRUCTION_HEADER(Lambda)
 
     static MLambda *New(MDefinition *scopeChain, JSFunction *fun) {
         return new MLambda(scopeChain, fun);
     }
     MDefinition *scopeChain() const {
         return getOperand(0);
     }
     JSFunction *fun() const {
@@ -3085,17 +3085,17 @@ class MImplicitThis
     MImplicitThis(MDefinition *callee)
       : MUnaryInstruction(callee)
     {
         setResultType(MIRType_Value);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(ImplicitThis);
+    INSTRUCTION_HEADER(ImplicitThis)
 
     static MImplicitThis *New(MDefinition *callee) {
         return new MImplicitThis(callee);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -3115,17 +3115,17 @@ class MSlots
     MSlots(MDefinition *object)
       : MUnaryInstruction(object)
     {
         setResultType(MIRType_Slots);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(Slots);
+    INSTRUCTION_HEADER(Slots)
 
     static MSlots *New(MDefinition *object) {
         return new MSlots(object);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -3148,17 +3148,17 @@ class MElements
     MElements(MDefinition *object)
       : MUnaryInstruction(object)
     {
         setResultType(MIRType_Elements);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(Elements);
+    INSTRUCTION_HEADER(Elements)
 
     static MElements *New(MDefinition *object) {
         return new MElements(object);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -3182,17 +3182,17 @@ class MConstantElements : public MNullar
     MConstantElements(void *v)
       : value_(v)
     {
         setResultType(MIRType_Elements);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(ConstantElements);
+    INSTRUCTION_HEADER(ConstantElements)
     static MConstantElements *New(void *v) {
         return new MConstantElements(v);
     }
 
     void *value() const {
         return value_;
     }
 
@@ -3218,17 +3218,17 @@ class MInitializedLength
     MInitializedLength(MDefinition *elements)
       : MUnaryInstruction(elements)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(InitializedLength);
+    INSTRUCTION_HEADER(InitializedLength)
 
     static MInitializedLength *New(MDefinition *elements) {
         return new MInitializedLength(elements);
     }
 
     MDefinition *elements() const {
         return getOperand(0);
     }
@@ -3246,17 +3246,17 @@ class MSetInitializedLength
 {
     MSetInitializedLength(MDefinition *elements, MDefinition *index)
     {
         initOperand(0, elements);
         initOperand(1, index);
     }
 
   public:
-    INSTRUCTION_HEADER(SetInitializedLength);
+    INSTRUCTION_HEADER(SetInitializedLength)
 
     static MSetInitializedLength *New(MDefinition *elements, MDefinition *index) {
         return new MSetInitializedLength(elements, index);
     }
 
     MDefinition *elements() const {
         return getOperand(0);
     }
@@ -3275,17 +3275,17 @@ class MArrayLength
   public:
     MArrayLength(MDefinition *elements)
       : MUnaryInstruction(elements)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
-    INSTRUCTION_HEADER(ArrayLength);
+    INSTRUCTION_HEADER(ArrayLength)
 
     MDefinition *elements() const {
         return getOperand(0);
     }
     bool congruentTo(MDefinition *const &ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
@@ -3301,17 +3301,17 @@ class MTypedArrayLength
     MTypedArrayLength(MDefinition *obj)
       : MUnaryInstruction(obj)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(TypedArrayLength);
+    INSTRUCTION_HEADER(TypedArrayLength)
 
     static MTypedArrayLength *New(MDefinition *obj) {
         return new MTypedArrayLength(obj);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -3336,17 +3336,17 @@ class MTypedArrayElements
     MTypedArrayElements(MDefinition *object)
       : MUnaryInstruction(object)
     {
         setResultType(MIRType_Elements);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(TypedArrayElements);
+    INSTRUCTION_HEADER(TypedArrayElements)
 
     static MTypedArrayElements *New(MDefinition *object) {
         return new MTypedArrayElements(object);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -3369,17 +3369,17 @@ class MNot
   public:
     MNot(MDefinition *elements)
       : MUnaryInstruction(elements)
     {
         setResultType(MIRType_Boolean);
         setMovable();
     }
 
-    INSTRUCTION_HEADER(Not);
+    INSTRUCTION_HEADER(Not)
 
     MDefinition *foldsTo(bool useValueNumbers);
 
     MDefinition *operand() const {
         return getOperand(0);
     }
 
     virtual AliasSet getAliasSet() const {
@@ -3408,17 +3408,17 @@ class MBoundsCheck
         JS_ASSERT(index->type() == MIRType_Int32);
         JS_ASSERT(length->type() == MIRType_Int32);
 
         // Returns the checked index.
         setResultType(MIRType_Int32);
     }
 
   public:
-    INSTRUCTION_HEADER(BoundsCheck);
+    INSTRUCTION_HEADER(BoundsCheck)
 
     static MBoundsCheck *New(MDefinition *index, MDefinition *length) {
         return new MBoundsCheck(index, length);
     }
     MDefinition *index() const {
         return getOperand(0);
     }
     MDefinition *length() const {
@@ -3459,17 +3459,17 @@ class MBoundsCheckLower
       : MUnaryInstruction(index), minimum_(0)
     {
         setGuard();
         setMovable();
         JS_ASSERT(index->type() == MIRType_Int32);
     }
 
   public:
-    INSTRUCTION_HEADER(BoundsCheckLower);
+    INSTRUCTION_HEADER(BoundsCheckLower)
 
     static MBoundsCheckLower *New(MDefinition *index) {
         return new MBoundsCheckLower(index);
     }
 
     MDefinition *index() const {
         return getOperand(0);
     }
@@ -3499,17 +3499,17 @@ class MLoadElement
     {
         setResultType(MIRType_Value);
         setMovable();
         JS_ASSERT(elements->type() == MIRType_Elements);
         JS_ASSERT(index->type() == MIRType_Int32);
     }
 
   public:
-    INSTRUCTION_HEADER(LoadElement);
+    INSTRUCTION_HEADER(LoadElement)
 
     static MLoadElement *New(MDefinition *elements, MDefinition *index, bool needsHoleCheck) {
         return new MLoadElement(elements, index, needsHoleCheck);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -3546,17 +3546,17 @@ class MLoadElementHole
         setResultType(MIRType_Value);
         setMovable();
         JS_ASSERT(elements->type() == MIRType_Elements);
         JS_ASSERT(index->type() == MIRType_Int32);
         JS_ASSERT(initLength->type() == MIRType_Int32);
     }
 
   public:
-    INSTRUCTION_HEADER(LoadElementHole);
+    INSTRUCTION_HEADER(LoadElementHole)
 
     static MLoadElementHole *New(MDefinition *elements, MDefinition *index,
                                  MDefinition *initLength, bool needsHoleCheck) {
         return new MLoadElementHole(elements, index, initLength, needsHoleCheck);
     }
 
     TypePolicy *typePolicy() {
         return this;
@@ -3615,17 +3615,17 @@ class MStoreElement
         initOperand(0, elements);
         initOperand(1, index);
         initOperand(2, value);
         JS_ASSERT(elements->type() == MIRType_Elements);
         JS_ASSERT(index->type() == MIRType_Int32);
     }
 
   public:
-    INSTRUCTION_HEADER(StoreElement);
+    INSTRUCTION_HEADER(StoreElement)
 
     static MStoreElement *New(MDefinition *elements, MDefinition *index, MDefinition *value) {
         return new MStoreElement(elements, index, value);
     }
     MDefinition *elements() const {
         return getOperand(0);
     }
     MDefinition *index() const {
@@ -3657,17 +3657,17 @@ class MStoreElementHole
         initOperand(1, elements);
         initOperand(2, index);
         initOperand(3, value);
         JS_ASSERT(elements->type() == MIRType_Elements);
         JS_ASSERT(index->type() == MIRType_Int32);
     }
 
   public:
-    INSTRUCTION_HEADER(StoreElementHole);
+    INSTRUCTION_HEADER(StoreElementHole)
 
     static MStoreElementHole *New(MDefinition *object, MDefinition *elements,
                                   MDefinition *index, MDefinition *value) {
         return new MStoreElementHole(object, elements, index, value);
     }
 
     MDefinition *object() const {
         return getOperand(0);
@@ -3708,17 +3708,17 @@ class MArrayPopShift
     bool maybeUndefined_;
 
     MArrayPopShift(MDefinition *object, Mode mode, bool needsHoleCheck, bool maybeUndefined)
       : MUnaryInstruction(object), mode_(mode), needsHoleCheck_(needsHoleCheck),
         maybeUndefined_(maybeUndefined)
     { }
 
   public:
-    INSTRUCTION_HEADER(ArrayPopShift);
+    INSTRUCTION_HEADER(ArrayPopShift)
 
     static MArrayPopShift *New(MDefinition *object, Mode mode, bool needsHoleCheck,
                                bool maybeUndefined) {
         return new MArrayPopShift(object, mode, needsHoleCheck, maybeUndefined);
     }
 
     MDefinition *object() const {
         return getOperand(0);
@@ -3747,17 +3747,17 @@ class MArrayPush
 {
     MArrayPush(MDefinition *object, MDefinition *value)
       : MBinaryInstruction(object, value)
     {
         setResultType(MIRType_Int32);
     }
 
   public:
-    INSTRUCTION_HEADER(ArrayPush);
+    INSTRUCTION_HEADER(ArrayPush)
 
     static MArrayPush *New(MDefinition *object, MDefinition *value) {
         return new MArrayPush(object, value);
     }
 
     MDefinition *object() const {
         return getOperand(0);
     }
@@ -3782,17 +3782,17 @@ class MArrayConcat
     MArrayConcat(MDefinition *lhs, MDefinition *rhs, HandleObject templateObj)
       : MBinaryInstruction(lhs, rhs),
         templateObj_(templateObj)
     {
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(ArrayConcat);
+    INSTRUCTION_HEADER(ArrayConcat)
 
     static MArrayConcat *New(MDefinition *lhs, MDefinition *rhs, HandleObject templateObj) {
         return new MArrayConcat(lhs, rhs, templateObj);
     }
 
     JSObject *templateObj() const {
         return templateObj_;
     }
@@ -3815,17 +3815,17 @@ class MLoadTypedArrayElement
         setResultType(MIRType_Value);
         setMovable();
         JS_ASSERT(elements->type() == MIRType_Elements);
         JS_ASSERT(index->type() == MIRType_Int32);
         JS_ASSERT(arrayType >= 0 && arrayType < TypedArray::TYPE_MAX);
     }
 
   public:
-    INSTRUCTION_HEADER(LoadTypedArrayElement);
+    INSTRUCTION_HEADER(LoadTypedArrayElement)
 
     static MLoadTypedArrayElement *New(MDefinition *elements, MDefinition *index, int arrayType) {
         return new MLoadTypedArrayElement(elements, index, arrayType);
     }
 
     int arrayType() const {
         return arrayType_;
     }
@@ -3858,17 +3858,17 @@ class MLoadTypedArrayElementHole
     {
         setResultType(MIRType_Value);
         setMovable();
         JS_ASSERT(index->type() == MIRType_Int32);
         JS_ASSERT(arrayType >= 0 && arrayType < TypedArray::TYPE_MAX);
     }
 
   public:
-    INSTRUCTION_HEADER(LoadTypedArrayElementHole);
+    INSTRUCTION_HEADER(LoadTypedArrayElementHole)
 
     static MLoadTypedArrayElementHole *New(MDefinition *object, MDefinition *index, int arrayType, bool allowDouble) {
         return new MLoadTypedArrayElementHole(object, index, arrayType, allowDouble);
     }
 
     int arrayType() const {
         return arrayType_;
     }
@@ -3907,17 +3907,17 @@ class MStoreTypedArrayElement
         setResultType(MIRType_Value);
         setMovable();
         JS_ASSERT(elements->type() == MIRType_Elements);
         JS_ASSERT(index->type() == MIRType_Int32);
         JS_ASSERT(arrayType >= 0 && arrayType < TypedArray::TYPE_MAX);
     }
 
   public:
-    INSTRUCTION_HEADER(StoreTypedArrayElement);
+    INSTRUCTION_HEADER(StoreTypedArrayElement)
 
     static MStoreTypedArrayElement *New(MDefinition *elements, MDefinition *index, MDefinition *value,
                                         int arrayType) {
         return new MStoreTypedArrayElement(elements, index, value, arrayType);
     }
 
     int arrayType() const {
         return arrayType_;
@@ -3956,17 +3956,17 @@ class MClampToUint8
     MClampToUint8(MDefinition *input)
       : MUnaryInstruction(input)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(ClampToUint8);
+    INSTRUCTION_HEADER(ClampToUint8)
 
     static MClampToUint8 *New(MDefinition *input) {
         return new MClampToUint8(input);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
 
     MDefinition *input() const {
@@ -3994,17 +3994,17 @@ class MLoadFixedSlot
     MLoadFixedSlot(MDefinition *obj, size_t slot)
       : MUnaryInstruction(obj), slot_(slot)
     {
         setResultType(MIRType_Value);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(LoadFixedSlot);
+    INSTRUCTION_HEADER(LoadFixedSlot)
 
     static MLoadFixedSlot *New(MDefinition *obj, size_t slot) {
         return new MLoadFixedSlot(obj, slot);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -4037,17 +4037,17 @@ class MStoreFixedSlot
 
     MStoreFixedSlot(MDefinition *obj, MDefinition *rval, size_t slot, bool barrier)
       : MBinaryInstruction(obj, rval),
         needsBarrier_(barrier),
         slot_(slot)
     {}
 
   public:
-    INSTRUCTION_HEADER(StoreFixedSlot);
+    INSTRUCTION_HEADER(StoreFixedSlot)
 
     static MStoreFixedSlot *New(MDefinition *obj, size_t slot, MDefinition *rval) {
         return new MStoreFixedSlot(obj, rval, slot, false);
     }
     static MStoreFixedSlot *NewBarriered(MDefinition *obj, size_t slot, MDefinition *rval) {
         return new MStoreFixedSlot(obj, rval, slot, true);
     }
 
@@ -4170,17 +4170,17 @@ class MGetPropertyCache
 
         // The cache will invalidate if there are objects with e.g. lookup or
         // resolve hooks on the proto chain. setGuard ensures this check is not
         // eliminated.
         setGuard();
     }
 
   public:
-    INSTRUCTION_HEADER(GetPropertyCache);
+    INSTRUCTION_HEADER(GetPropertyCache)
 
     static MGetPropertyCache *New(MDefinition *obj, HandlePropertyName name) {
         return new MGetPropertyCache(obj, name);
     }
 
     InlinePropertyTable *initInlinePropertyTable(jsbytecode *pc) {
         JS_ASSERT(inlinePropertyTable_ == NULL);
         inlinePropertyTable_ = new InlinePropertyTable(pc);
@@ -4285,17 +4285,17 @@ class MPolyInlineDispatch : public MCont
         JS_ASSERT(i < numSuccessors());
         if (inlinePropertyTable_ && (i == numSuccessors() - 1))
             fallbackPrepBlock_ = successor;
         else
             dispatchTable_[i].block = successor;
     }
 
   public:
-    INSTRUCTION_HEADER(PolyInlineDispatch);
+    INSTRUCTION_HEADER(PolyInlineDispatch)
 
     virtual MDefinition *getOperand(size_t index) const {
         JS_ASSERT(index == 0);
         return operand_;
     }
 
     virtual size_t numOperands() const {
         return 1;
@@ -4400,17 +4400,17 @@ class MGetElementCache
 
     MGetElementCache(MDefinition *obj, MDefinition *value, bool monitoredResult)
       : MBinaryInstruction(obj, value), monitoredResult_(monitoredResult)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(GetElementCache);
+    INSTRUCTION_HEADER(GetElementCache)
 
     static MGetElementCache *New(MDefinition *obj, MDefinition *value, bool monitoredResult) {
         return new MGetElementCache(obj, value, monitoredResult);
     }
 
     MDefinition *object() const {
         return getOperand(0);
     }
@@ -4435,17 +4435,17 @@ class MBindNameCache
 
     MBindNameCache(MDefinition *scopeChain, PropertyName *name, JSScript *script, jsbytecode *pc)
       : MUnaryInstruction(scopeChain), name_(name), script_(script), pc_(pc)
     {
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(BindNameCache);
+    INSTRUCTION_HEADER(BindNameCache)
 
     static MBindNameCache *New(MDefinition *scopeChain, PropertyName *name, JSScript *script,
                                jsbytecode *pc) {
         return new MBindNameCache(scopeChain, name, script, pc);
     }
 
     TypePolicy *typePolicy() {
         return this;
@@ -4478,17 +4478,17 @@ class MGuardShape
         bailoutKind_(bailoutKind)
     {
         setGuard();
         setMovable();
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(GuardShape);
+    INSTRUCTION_HEADER(GuardShape)
 
     static MGuardShape *New(MDefinition *obj, const Shape *shape, BailoutKind bailoutKind) {
         return new MGuardShape(obj, shape, bailoutKind);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -4526,17 +4526,17 @@ class MGuardClass
       : MUnaryInstruction(obj),
         class_(clasp)
     {
         setGuard();
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(GuardClass);
+    INSTRUCTION_HEADER(GuardClass)
 
     static MGuardClass *New(MDefinition *obj, const Class *clasp) {
         return new MGuardClass(obj, clasp);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -4570,17 +4570,17 @@ class MLoadSlot
         slot_(slot)
     {
         setResultType(MIRType_Value);
         setMovable();
         JS_ASSERT(slots->type() == MIRType_Slots);
     }
 
   public:
-    INSTRUCTION_HEADER(LoadSlot);
+    INSTRUCTION_HEADER(LoadSlot)
 
     static MLoadSlot *New(MDefinition *slots, uint32_t slot) {
         return new MLoadSlot(slots, slot);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -4610,17 +4610,17 @@ class MFunctionEnvironment
 {
   public:
     MFunctionEnvironment(MDefinition *function)
         : MUnaryInstruction(function)
     {
         setResultType(MIRType_Object);
     }
 
-    INSTRUCTION_HEADER(FunctionEnvironment);
+    INSTRUCTION_HEADER(FunctionEnvironment)
 
     static MFunctionEnvironment *New(MDefinition *function) {
         return new MFunctionEnvironment(function);
     }
 
     MDefinition *function() const {
         return getOperand(0);
     }
@@ -4640,17 +4640,17 @@ class MStoreSlot
           slot_(slot),
           slotType_(MIRType_Value),
           needsBarrier_(barrier)
     {
         JS_ASSERT(slots->type() == MIRType_Slots);
     }
 
   public:
-    INSTRUCTION_HEADER(StoreSlot);
+    INSTRUCTION_HEADER(StoreSlot)
 
     static MStoreSlot *New(MDefinition *slots, uint32_t slot, MDefinition *value) {
         return new MStoreSlot(slots, slot, value, false);
     }
     static MStoreSlot *NewBarriered(MDefinition *slots, uint32_t slot, MDefinition *value) {
         return new MStoreSlot(slots, slot, value, true);
     }
 
@@ -4702,17 +4702,17 @@ class MGetNameCache
       : MUnaryInstruction(obj),
         name_(name),
         kind_(kind)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(GetNameCache);
+    INSTRUCTION_HEADER(GetNameCache)
 
     static MGetNameCache *New(MDefinition *obj, HandlePropertyName name, AccessKind kind) {
         return new MGetNameCache(obj, name, kind);
     }
     TypePolicy *typePolicy() {
         return this;
     }
     MDefinition *scopeObj() const {
@@ -4732,17 +4732,17 @@ class MCallGetIntrinsicValue : public MN
 
     MCallGetIntrinsicValue(HandlePropertyName name)
       : name_(name)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(CallGetIntrinsicValue);
+    INSTRUCTION_HEADER(CallGetIntrinsicValue)
 
     static MCallGetIntrinsicValue *New(HandlePropertyName name) {
         return new MCallGetIntrinsicValue(name);
     }
     PropertyName *name() const {
         return name_;
     }
 };
@@ -4791,17 +4791,17 @@ class MDeleteProperty
     MDeleteProperty(MDefinition *val, HandlePropertyName name)
       : MUnaryInstruction(val),
         name_(name)
     {
         setResultType(MIRType_Boolean);
     }
 
   public:
-    INSTRUCTION_HEADER(DeleteProperty);
+    INSTRUCTION_HEADER(DeleteProperty)
 
     static MDeleteProperty *New(MDefinition *obj, HandlePropertyName name) {
         return new MDeleteProperty(obj, name);
     }
     MDefinition *value() const {
         return getOperand(0);
     }
     PropertyName *name() const {
@@ -4819,17 +4819,17 @@ class MCallSetProperty
     public CallSetElementPolicy
 {
     MCallSetProperty(MDefinition *obj, MDefinition *value, HandlePropertyName name, bool strict)
       : MSetPropertyInstruction(obj, value, name, strict)
     {
     }
 
   public:
-    INSTRUCTION_HEADER(CallSetProperty);
+    INSTRUCTION_HEADER(CallSetProperty)
 
     static MCallSetProperty *New(MDefinition *obj, MDefinition *value, HandlePropertyName name, bool strict) {
         return new MCallSetProperty(obj, value, name, strict);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -4840,17 +4840,17 @@ class MSetPropertyCache
     public SingleObjectPolicy
 {
     MSetPropertyCache(MDefinition *obj, MDefinition *value, HandlePropertyName name, bool strict)
       : MSetPropertyInstruction(obj, value, name, strict)
     {
     }
 
   public:
-    INSTRUCTION_HEADER(SetPropertyCache);
+    INSTRUCTION_HEADER(SetPropertyCache)
 
     static MSetPropertyCache *New(MDefinition *obj, MDefinition *value, HandlePropertyName name, bool strict) {
         return new MSetPropertyCache(obj, value, name, strict);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -4866,17 +4866,17 @@ class MCallGetProperty
     MCallGetProperty(MDefinition *value, HandlePropertyName name)
       : MUnaryInstruction(value), name_(name),
         idempotent_(false)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(CallGetProperty);
+    INSTRUCTION_HEADER(CallGetProperty)
 
     static MCallGetProperty *New(MDefinition *value, HandlePropertyName name) {
         return new MCallGetProperty(value, name);
     }
     MDefinition *value() const {
         return getOperand(0);
     }
     PropertyName *name() const {
@@ -4907,17 +4907,17 @@ class MCallGetElement
 {
     MCallGetElement(MDefinition *lhs, MDefinition *rhs)
       : MBinaryInstruction(lhs, rhs)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(CallGetElement);
+    INSTRUCTION_HEADER(CallGetElement)
 
     static MCallGetElement *New(MDefinition *lhs, MDefinition *rhs) {
         return new MCallGetElement(lhs, rhs);
     }
     TypePolicy *typePolicy() {
         return this;
     }
 };
@@ -4928,17 +4928,17 @@ class MCallSetElement
 {
     MCallSetElement(MDefinition *object, MDefinition *index, MDefinition *value) {
         initOperand(0, object);
         initOperand(1, index);
         initOperand(2, value);
     }
 
   public:
-    INSTRUCTION_HEADER(CallSetElement);
+    INSTRUCTION_HEADER(CallSetElement)
 
     static MCallSetElement *New(MDefinition *object, MDefinition *index, MDefinition *value) {
         return new MCallSetElement(object, index, value);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -4962,17 +4962,17 @@ class MSetDOMProperty
     MSetDOMProperty(const JSJitPropertyOp func, MDefinition *obj, MDefinition *val)
       : func_(func)
     {
         initOperand(0, obj);
         initOperand(1, val);
     }
 
   public:
-    INSTRUCTION_HEADER(SetDOMProperty);
+    INSTRUCTION_HEADER(SetDOMProperty)
 
     static MSetDOMProperty *New(const JSJitPropertyOp func, MDefinition *obj, MDefinition *val)
     {
         return new MSetDOMProperty(func, obj, val);
     }
 
     const JSJitPropertyOp fun() {
         return func_;
@@ -5016,17 +5016,17 @@ class MGetDOMProperty
     }
 
   protected:
     const JSJitInfo *info() const {
         return info_;
     }
 
   public:
-    INSTRUCTION_HEADER(GetDOMProperty);
+    INSTRUCTION_HEADER(GetDOMProperty)
 
     static MGetDOMProperty *New(const JSJitInfo *info, MDefinition *obj, MDefinition *guard)
     {
         return new MGetDOMProperty(info, obj, guard);
     }
 
     const JSJitPropertyOp fun() {
         return info_->op;
@@ -5075,17 +5075,17 @@ class MStringLength
 {
     MStringLength(MDefinition *string)
       : MUnaryInstruction(string)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
   public:
-    INSTRUCTION_HEADER(StringLength);
+    INSTRUCTION_HEADER(StringLength)
 
     static MStringLength *New(MDefinition *string) {
         return new MStringLength(string);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
 
     TypePolicy *typePolicy() {
@@ -5113,17 +5113,17 @@ class MFloor
   public:
     MFloor(MDefinition *num)
       : MUnaryInstruction(num)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
-    INSTRUCTION_HEADER(Floor);
+    INSTRUCTION_HEADER(Floor)
 
     MDefinition *num() const {
         return getOperand(0);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     TypePolicy *typePolicy() {
@@ -5139,17 +5139,17 @@ class MRound
   public:
     MRound(MDefinition *num)
       : MUnaryInstruction(num)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
-    INSTRUCTION_HEADER(Round);
+    INSTRUCTION_HEADER(Round)
 
     MDefinition *num() const {
         return getOperand(0);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     TypePolicy *typePolicy() {
@@ -5165,17 +5165,17 @@ class MIteratorStart
 
     MIteratorStart(MDefinition *obj, uint8_t flags)
       : MUnaryInstruction(obj), flags_(flags)
     {
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(IteratorStart);
+    INSTRUCTION_HEADER(IteratorStart)
 
     static MIteratorStart *New(MDefinition *obj, uint8_t flags) {
         return new MIteratorStart(obj, flags);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -5193,17 +5193,17 @@ class MIteratorNext
 {
     MIteratorNext(MDefinition *iter)
       : MUnaryInstruction(iter)
     {
         setResultType(MIRType_Value);
     }
 
   public:
-    INSTRUCTION_HEADER(IteratorNext);
+    INSTRUCTION_HEADER(IteratorNext)
 
     static MIteratorNext *New(MDefinition *iter) {
         return new MIteratorNext(iter);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -5218,17 +5218,17 @@ class MIteratorMore
 {
     MIteratorMore(MDefinition *iter)
       : MUnaryInstruction(iter)
     {
         setResultType(MIRType_Boolean);
     }
 
   public:
-    INSTRUCTION_HEADER(IteratorMore);
+    INSTRUCTION_HEADER(IteratorMore)
 
     static MIteratorMore *New(MDefinition *iter) {
         return new MIteratorMore(iter);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -5241,17 +5241,17 @@ class MIteratorEnd
   : public MUnaryInstruction,
     public SingleObjectPolicy
 {
     MIteratorEnd(MDefinition *iter)
       : MUnaryInstruction(iter)
     { }
 
   public:
-    INSTRUCTION_HEADER(IteratorEnd);
+    INSTRUCTION_HEADER(IteratorEnd)
 
     static MIteratorEnd *New(MDefinition *iter) {
         return new MIteratorEnd(iter);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
@@ -5267,17 +5267,17 @@ class MIn
 {
   public:
     MIn(MDefinition *key, MDefinition *obj)
       : MBinaryInstruction(key, obj)
     {
         setResultType(MIRType_Boolean);
     }
 
-    INSTRUCTION_HEADER(In);
+    INSTRUCTION_HEADER(In)
 
     TypePolicy *typePolicy() {
         return this;
     }
 };
 
 
 // Test whether the index is in the array bounds or a hole.
@@ -5293,17 +5293,17 @@ class MInArray
         setResultType(MIRType_Boolean);
         setMovable();
         JS_ASSERT(elements->type() == MIRType_Elements);
         JS_ASSERT(index->type() == MIRType_Int32);
         JS_ASSERT(initLength->type() == MIRType_Int32);
     }
 
   public:
-    INSTRUCTION_HEADER(InArray);
+    INSTRUCTION_HEADER(InArray)
 
     static MInArray *New(MDefinition *elements, MDefinition *index,
                          MDefinition *initLength, bool needsHoleCheck) {
         return new MInArray(elements, index, initLength, needsHoleCheck);
     }
 
     MDefinition *elements() const {
         return getOperand(0);
@@ -5332,17 +5332,17 @@ class MInstanceOf
   public:
     MInstanceOf(MDefinition *obj, RawObject proto)
       : MUnaryInstruction(obj),
         protoObj_(proto)
     {
         setResultType(MIRType_Boolean);
     }
 
-    INSTRUCTION_HEADER(InstanceOf);
+    INSTRUCTION_HEADER(InstanceOf)
 
     TypePolicy *typePolicy() {
         return this;
     }
 
     RawObject prototypeObject() {
         return protoObj_;
     }
@@ -5355,33 +5355,33 @@ class MCallInstanceOf
 {
   public:
     MCallInstanceOf(MDefinition *obj, MDefinition *proto)
       : MBinaryInstruction(obj, proto)
     {
         setResultType(MIRType_Boolean);
     }
 
-    INSTRUCTION_HEADER(CallInstanceOf);
+    INSTRUCTION_HEADER(CallInstanceOf)
 
     TypePolicy *typePolicy() {
         return this;
     }
 };
 
 class MArgumentsLength : public MNullaryInstruction
 {
     MArgumentsLength()
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(ArgumentsLength);
+    INSTRUCTION_HEADER(ArgumentsLength)
 
     static MArgumentsLength *New() {
         return new MArgumentsLength();
     }
 
     bool congruentTo(MDefinition *const &ins) const {
         return congruentIfOperandsEqual(ins);
     }
@@ -5399,17 +5399,17 @@ class MGetArgument
     MGetArgument(MDefinition *idx)
       : MUnaryInstruction(idx)
     {
         setResultType(MIRType_Value);
         setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(GetArgument);
+    INSTRUCTION_HEADER(GetArgument)
 
     static MGetArgument *New(MDefinition *idx) {
         return new MGetArgument(idx);
     }
 
     MDefinition *index() const {
         return getOperand(0);
     }
@@ -5440,17 +5440,17 @@ class MTypeBarrier : public MUnaryInstru
         setGuard();
         setMovable();
         bailoutKind_ = def->isEffectful()
                        ? Bailout_TypeBarrier
                        : Bailout_Normal;
     }
 
   public:
-    INSTRUCTION_HEADER(TypeBarrier);
+    INSTRUCTION_HEADER(TypeBarrier)
 
     static MTypeBarrier *New(MDefinition *def, const types::TypeSet *types) {
         return new MTypeBarrier(def, types);
     }
     bool congruentTo(MDefinition * const &def) const {
         return false;
     }
     MDefinition *input() const {
@@ -5483,17 +5483,17 @@ class MMonitorTypes : public MUnaryInstr
         typeSet_(types)
     {
         setResultType(MIRType_Value);
         setGuard();
         JS_ASSERT(!types->unknown());
     }
 
   public:
-    INSTRUCTION_HEADER(MonitorTypes);
+    INSTRUCTION_HEADER(MonitorTypes)
 
     static MMonitorTypes *New(MDefinition *def, const types::TypeSet *types) {
         return new MMonitorTypes(def, types);
     }
     MDefinition *input() const {
         return getOperand(0);
     }
     const types::TypeSet *typeSet() const {
@@ -5510,17 +5510,17 @@ class MNewSlots : public MNullaryInstruc
 
     MNewSlots(unsigned nslots)
       : nslots_(nslots)
     {
         setResultType(MIRType_Slots);
     }
 
   public:
-    INSTRUCTION_HEADER(NewSlots);
+    INSTRUCTION_HEADER(NewSlots)
 
     static MNewSlots *New(unsigned nslots) {
         return new MNewSlots(nslots);
     }
     unsigned nslots() const {
         return nslots_;
     }
     AliasSet getAliasSet() const {
@@ -5561,17 +5561,17 @@ class MNewCallObject : public MUnaryInst
     MNewCallObject(HandleObject templateObj, MDefinition *slots)
       : MUnaryInstruction(slots),
         templateObj_(templateObj)
     {
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(NewCallObject);
+    INSTRUCTION_HEADER(NewCallObject)
 
     static MNewCallObject *New(HandleObject templateObj, MDefinition *slots) {
         return new MNewCallObject(templateObj, slots);
     }
 
     MDefinition *slots() {
         return getOperand(0);
     }
@@ -5592,17 +5592,17 @@ class MNewStringObject :
     MNewStringObject(MDefinition *input, HandleObject templateObj)
       : MUnaryInstruction(input),
         templateObj_(templateObj)
     {
         setResultType(MIRType_Object);
     }
 
   public:
-    INSTRUCTION_HEADER(NewStringObject);
+    INSTRUCTION_HEADER(NewStringObject)
 
     static MNewStringObject *New(MDefinition *input, HandleObject templateObj) {
         return new MNewStringObject(input, templateObj);
     }
 
     MDefinition *input() const {
         return getOperand(0);
     }
@@ -5639,17 +5639,17 @@ class MFunctionBoundary : public MNullar
       : script_(script), type_(type), inlineLevel_(inlineLevel)
     {
         JS_ASSERT_IF(type != Inline_Exit, script != NULL);
         JS_ASSERT_IF(type == Inline_Enter, inlineLevel != 0);
         setGuard();
     }
 
   public:
-    INSTRUCTION_HEADER(FunctionBoundary);
+    INSTRUCTION_HEADER(FunctionBoundary)
 
     static MFunctionBoundary *New(JSScript *script, Type type,
                                   unsigned inlineLevel = 0) {
         return new MFunctionBoundary(script, type, inlineLevel);
     }
 
     JSScript *script() {
         return script_;
--- a/js/src/ion/VMFunctions.h
+++ b/js/src/ion/VMFunctions.h
@@ -338,41 +338,41 @@ struct FunctionInfo<R (*)(JSContext *)> 
     { }
 };
 
 // Specialize the class for each number of argument used by VMFunction.
 // Keep it verbose unless you find a readable macro for it.
 template <class R, class A1>
 struct FunctionInfo<R (*)(JSContext *, A1)> : public VMFunction {
     typedef R (*pf)(JSContext *, A1);
-    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_1);
+    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_1)
 };
 
 template <class R, class A1, class A2>
 struct FunctionInfo<R (*)(JSContext *, A1, A2)> : public VMFunction {
     typedef R (*pf)(JSContext *, A1, A2);
-    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_2);
+    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_2)
 };
 
 template <class R, class A1, class A2, class A3>
 struct FunctionInfo<R (*)(JSContext *, A1, A2, A3)> : public VMFunction {
     typedef R (*pf)(JSContext *, A1, A2, A3);
-    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_3);
+    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_3)
 };
 
 template <class R, class A1, class A2, class A3, class A4>
 struct FunctionInfo<R (*)(JSContext *, A1, A2, A3, A4)> : public VMFunction {
     typedef R (*pf)(JSContext *, A1, A2, A3, A4);
-    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_4);
+    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_4)
 };
 
 template <class R, class A1, class A2, class A3, class A4, class A5>
     struct FunctionInfo<R (*)(JSContext *, A1, A2, A3, A4, A5)> : public VMFunction {
     typedef R (*pf)(JSContext *, A1, A2, A3, A4, A5);
-    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_5);
+    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_5)
 };
 
 #undef FUNCTION_INFO_STRUCT_BODY
 
 #undef FOR_EACH_ARGS_5
 #undef FOR_EACH_ARGS_4
 #undef FOR_EACH_ARGS_3
 #undef FOR_EACH_ARGS_2
--- a/js/src/ion/shared/LIR-x86-shared.h
+++ b/js/src/ion/shared/LIR-x86-shared.h
@@ -9,17 +9,17 @@
 #define jsion_lir_x86_shared_h__
 
 namespace js {
 namespace ion {
 
 class LDivI : public LBinaryMath<1>
 {
   public:
-    LIR_HEADER(DivI);
+    LIR_HEADER(DivI)
 
     LDivI(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
 
     const LDefinition *remainder() {
@@ -28,34 +28,34 @@ class LDivI : public LBinaryMath<1>
     MDiv *mir() const {
         return mir_->toDiv();
     }
 };
 
 class LModI : public LBinaryMath<1>
 {
   public:
-    LIR_HEADER(ModI);
+    LIR_HEADER(ModI)
 
     LModI(const LAllocation &lhs, const LAllocation &rhs) {
         setOperand(0, lhs);
         setOperand(1, rhs);
     }
 
     const LDefinition *remainder() {
         return getDef(0);
     }
 };
 
 class LModPowTwoI : public LInstructionHelper<1,1,0>
 {
     const int32_t shift_;
 
   public:
-    LIR_HEADER(ModPowTwoI);
+    LIR_HEADER(ModPowTwoI)
 
     LModPowTwoI(const LAllocation &lhs, int32_t shift)
       : shift_(shift)
     {
         setOperand(0, lhs);
     }
 
     int32_t shift() const {
@@ -65,17 +65,17 @@ class LModPowTwoI : public LInstructionH
         return getDef(0);
     }
 };
 
 // Double raised to a half power.
 class LPowHalfD : public LInstructionHelper<1, 1, 1>
 {
   public:
-    LIR_HEADER(PowHalfD);
+    LIR_HEADER(PowHalfD)
     LPowHalfD(const LAllocation &input, const LDefinition &temp) {
         setOperand(0, input);
         setTemp(0, temp);
     }
 
     const LAllocation *input() {
         return getOperand(0);
     }
@@ -86,17 +86,17 @@ class LPowHalfD : public LInstructionHel
         return getDef(0);
     }
 };
 
 // Takes a tableswitch with an integer to decide
 class LTableSwitch : public LInstructionHelper<0, 1, 2>
 {
   public:
-    LIR_HEADER(TableSwitch);
+    LIR_HEADER(TableSwitch)
 
     LTableSwitch(const LAllocation &in, const LDefinition &inputCopy,
                  const LDefinition &jumpTablePointer, MTableSwitch *ins)
     {
         setOperand(0, in);
         setTemp(0, inputCopy);
         setTemp(1, jumpTablePointer);
         setMir(ins);
@@ -116,17 +116,17 @@ class LTableSwitch : public LInstruction
         return getTemp(1)->output();
     }
 };
 
 // Takes a tableswitch with a value to decide
 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
 {
   public:
-    LIR_HEADER(TableSwitchV);
+    LIR_HEADER(TableSwitchV)
 
     LTableSwitchV(const LDefinition &inputCopy, const LDefinition &floatCopy,
                   const LDefinition &jumpTablePointer, MTableSwitch *ins)
     {
         setTemp(0, inputCopy);
         setTemp(1, floatCopy);
         setTemp(2, jumpTablePointer);
         setMir(ins);
@@ -148,46 +148,46 @@ class LTableSwitchV : public LInstructio
         return getTemp(2)->output();
     }
 };
 
 // Guard against an object's shape.
 class LGuardShape : public LInstructionHelper<0, 1, 0>
 {
   public:
-    LIR_HEADER(GuardShape);
+    LIR_HEADER(GuardShape)
 
     LGuardShape(const LAllocation &in) {
         setOperand(0, in);
     }
     const MGuardShape *mir() const {
         return mir_->toGuardShape();
     }
 };
 
 class LRecompileCheck : public LInstructionHelper<0, 0, 0>
 {
   public:
-    LIR_HEADER(RecompileCheck);
+    LIR_HEADER(RecompileCheck)
 
     const MRecompileCheck *mir() const {
         return mir_->toRecompileCheck();
     }
 };
 
 class LInterruptCheck : public LInstructionHelper<0, 0, 0>
 {
   public:
-    LIR_HEADER(InterruptCheck);
+    LIR_HEADER(InterruptCheck)
 };
 
 class LMulI : public LBinaryMath<0, 1>
 {
   public:
-    LIR_HEADER(MulI);
+    LIR_HEADER(MulI)
 
     LMulI(const LAllocation &lhs, const LAllocation &rhs, const LAllocation &lhsCopy) {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setOperand(2, lhsCopy);
     }
 
     MMul *mir() {
--- a/js/src/ion/shared/Lowering-shared.h
+++ b/js/src/ion/shared/Lowering-shared.h
@@ -161,16 +161,21 @@ class LIRGeneratorShared : public MInstr
 
     // Marks this instruction as needing to call into either the VM or GC. This
     // function may build a snapshot that captures the result of its own
     // instruction, and as such, should generally be called after define*().
     bool assignSafepoint(LInstruction *ins, MInstruction *mir);
 
   public:
     bool visitConstant(MConstant *ins);
+
+    // Whether to generate typed reads for element accesses with hole checks.
+    static bool allowTypedElementHoleCheck() {
+        return false;
+    }
 };
 
 } // namespace ion
 } // namespace js
 
 #endif // jsion_lowering_shared_h__
 
 
--- a/js/src/ion/x64/LIR-x64.h
+++ b/js/src/ion/x64/LIR-x64.h
@@ -14,17 +14,17 @@ namespace js {
 namespace ion {
 
 // Given a typed input, returns an untyped box.
 class LBox : public LInstructionHelper<1, 1, 0>
 {
     MIRType type_;
 
   public:
-    LIR_HEADER(Box);
+    LIR_HEADER(Box)
 
     LBox(MIRType type, const LAllocation &payload)
       : type_(type)
     {
         setOperand(0, payload);
     }
 
     MIRType type() const {
@@ -45,39 +45,39 @@ class LUnboxBase : public LInstructionHe
 
     MUnbox *mir() const {
         return mir_->toUnbox();
     }
 };
 
 class LUnbox : public LUnboxBase {
   public:
-    LIR_HEADER(Unbox);
+    LIR_HEADER(Unbox)
 
     LUnbox(const LAllocation &input)
       : LUnboxBase(input)
     { }
 };
 
 class LUnboxDouble : public LUnboxBase {
   public:
-    LIR_HEADER(UnboxDouble);
+    LIR_HEADER(UnboxDouble)
 
     LUnboxDouble(const LAllocation &input)
       : LUnboxBase(input)
     { }
 };
 
 // Constant double.
 class LDouble : public LInstructionHelper<1, 0, 0>
 {
     double d_;
 
   public:
-    LIR_HEADER(Double);
+    LIR_HEADER(Double)
 
     LDouble(double d)
       : d_(d)
     { }
 
     double getDouble() const {
         return d_;
     }
--- a/js/src/ion/x86/CodeGenerator-x86.cpp
+++ b/js/src/ion/x86/CodeGenerator-x86.cpp
@@ -225,22 +225,27 @@ CodeGeneratorX86::visitStoreSlotT(LStore
     return true;
 }
 
 bool
 CodeGeneratorX86::visitLoadElementT(LLoadElementT *load)
 {
     Operand source = createArrayElementOperand(ToRegister(load->elements()), load->index());
 
+    if (load->mir()->needsHoleCheck()) {
+        Assembler::Condition cond = masm.testMagic(Assembler::Equal, source);
+        if (!bailoutIf(cond, load->snapshot()))
+            return false;
+    }
+
     if (load->mir()->type() == MIRType_Double)
         masm.loadInt32OrDouble(source, ToFloatRegister(load->output()));
     else
         masm.movl(masm.ToPayload(source), ToRegister(load->output()));
 
-    JS_ASSERT(!load->mir()->needsHoleCheck());
     return true;
 }
 
 void
 CodeGeneratorX86::storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
                                     const Register &elements, const LAllocation *index)
 {
     Operand dest = createArrayElementOperand(elements, index);
--- a/js/src/ion/x86/Lowering-x86.h
+++ b/js/src/ion/x86/Lowering-x86.h
@@ -44,16 +44,20 @@ class LIRGeneratorX86 : public LIRGenera
 
   public:
     bool visitConstant(MConstant *ins);
     bool visitBox(MBox *box);
     bool visitUnbox(MUnbox *unbox);
     bool visitReturn(MReturn *ret);
     bool visitStoreTypedArrayElement(MStoreTypedArrayElement *ins);
     bool lowerPhi(MPhi *phi);
+
+    static bool allowTypedElementHoleCheck() {
+        return true;
+    }
 };
 
 typedef LIRGeneratorX86 LIRGeneratorSpecific;
 
 } // namespace js
 } // namespace ion
 
 #endif // jsion_ion_lowering_x86_h__
--- a/js/src/ion/x86/MacroAssembler-x86.h
+++ b/js/src/ion/x86/MacroAssembler-x86.h
@@ -267,16 +267,21 @@ class MacroAssemblerX86 : public MacroAs
         cmpl(tagOf(address), ImmTag(JSVAL_TAG_MAGIC));
         return cond;
     }
     Condition testMagic(Condition cond, const Register &tag) {
         JS_ASSERT(cond == Equal || cond == NotEqual);
         cmpl(tag, ImmTag(JSVAL_TAG_MAGIC));
         return cond;
     }
+    Condition testMagic(Condition cond, const Operand &operand) {
+        JS_ASSERT(cond == Equal || cond == NotEqual);
+        cmpl(ToType(operand), ImmTag(JSVAL_TAG_MAGIC));
+        return cond;
+    }
     Condition testPrimitive(Condition cond, const Register &tag) {
         JS_ASSERT(cond == Equal || cond == NotEqual);
         cmpl(tag, ImmTag(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));
         return cond == Equal ? Below : AboveOrEqual;
     }
     Condition testError(Condition cond, const Register &tag) {
         return testMagic(cond, tag);
     }
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -46,17 +46,17 @@ class TaggedProto
 
   private:
     JSObject *proto;
 };
 
 template <>
 struct RootKind<TaggedProto>
 {
-    static ThingRootKind rootKind() { return THING_ROOT_OBJECT; };
+    static ThingRootKind rootKind() { return THING_ROOT_OBJECT; }
 };
 
 template <> struct RootMethods<const TaggedProto>
 {
     static TaggedProto initial() { return TaggedProto(); }
     static ThingRootKind kind() { return THING_ROOT_OBJECT; }
     static bool poisoned(const TaggedProto &v) { return IsPoisonedPtr(v.raw()); }
 };
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -44,18 +44,18 @@ class JS_FRIEND_API(Wrapper) : public Di
     };
 
     /*
      * Wrappers can explicitly specify that they are unsafe to unwrap from a
      * security perspective (as is the case for SecurityWrappers). If a wrapper
      * is not safe to unwrap, operations requiring full access to the underlying
      * object (via UnwrapObjectChecked) will throw. Otherwise, they will succeed.
      */
-    void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; };
-    bool isSafeToUnwrap() { return mSafeToUnwrap; };
+    void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; }
+    bool isSafeToUnwrap() { return mSafeToUnwrap; }
 
     static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
                          JSObject *parent, Wrapper *handler);
 
     static JSObject *Renew(JSContext *cx, JSObject *existing, JSObject *obj, Wrapper *handler);
 
     static Wrapper *wrapperHandler(RawObject wrapper);
 
--- a/js/src/methodjit/FrameState.h
+++ b/js/src/methodjit/FrameState.h
@@ -821,17 +821,17 @@ class FrameState
     //   nargs +
     //   nfixed +
     //   currently pushed stack slots
     uint32_t frameSlots() const { return uint32_t(a->sp - a->callee_); }
 
 #ifdef DEBUG
     void assertValidRegisterState() const;
 #else
-    inline void assertValidRegisterState() const {};
+    inline void assertValidRegisterState() const {}
 #endif
 
     // Return an address, relative to the StackFrame, that represents where
     // this FrameEntry is stored in memory. Note that this is its canonical
     // address, not its backing store. There is no guarantee that the memory
     // is coherent.
     Address addressOf(const FrameEntry *fe) const;
     Address addressOf(uint32_t slot) const { return addressOf(a->callee_ + slot); }
--- a/js/xpconnect/wrappers/ChromeObjectWrapper.h
+++ b/js/xpconnect/wrappers/ChromeObjectWrapper.h
@@ -19,17 +19,17 @@ namespace xpc {
 // custom class here to introduce custom behavior with respect to the prototype
 // chain.
 #define ChromeObjectWrapperBase \
   FilteringWrapper<js::CrossCompartmentSecurityWrapper, ExposedPropertiesOnly>
 
 class ChromeObjectWrapper : public ChromeObjectWrapperBase
 {
   public:
-    ChromeObjectWrapper() : ChromeObjectWrapperBase(0) {};
+    ChromeObjectWrapper() : ChromeObjectWrapperBase(0) {}
 
     /* Custom traps. */
     virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper,
                                        jsid id, bool set,
                                        js::PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool has(JSContext *cx, JSObject *wrapper, jsid id,
                      bool *bp) MOZ_OVERRIDE;
     virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver,
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -44,16 +44,17 @@ FrameLayerBuilder::DisplayItemData::Disp
 
   : mParent(aParent)
   , mLayer(aLayer)
   , mDisplayItemKey(aKey)
   , mContainerLayerGeneration(aGeneration)
   , mLayerState(aLayerState)
   , mUsed(true)
   , mIsInvalid(false)
+  , mIsVisible(true)
 {
 }
 
 FrameLayerBuilder::DisplayItemData::DisplayItemData(DisplayItemData &toCopy)
 {
   // This isn't actually a copy-constructor; notice that it steals toCopy's
   // mGeometry pointer.  Be careful.
   mParent = toCopy.mParent;
@@ -61,16 +62,17 @@ FrameLayerBuilder::DisplayItemData::Disp
   mInactiveManager = toCopy.mInactiveManager;
   mFrameList = toCopy.mFrameList;
   mGeometry = toCopy.mGeometry;
   mDisplayItemKey = toCopy.mDisplayItemKey;
   mClip = toCopy.mClip;
   mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
   mLayerState = toCopy.mLayerState;
   mUsed = toCopy.mUsed;
+  mIsVisible = toCopy.mIsVisible;
 }
 
 void
 FrameLayerBuilder::DisplayItemData::AddFrame(nsIFrame* aFrame)
 {
   mFrameList.AppendElement(aFrame);
 
   nsTArray<DisplayItemData*> *array = 
@@ -1095,42 +1097,45 @@ FrameLayerBuilder::GetDisplayItemDataFor
         return item;
       }
     }
   }
   return nullptr;
 }
 
 bool
-FrameLayerBuilder::HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
+FrameLayerBuilder::HasVisibleRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
 {
   nsTArray<DisplayItemData*> *array = 
     reinterpret_cast<nsTArray<DisplayItemData*>*>(aFrame->Properties().Get(LayerManagerDataProperty()));
   if (array) {
     for (uint32_t i = 0; i < array->Length(); i++) {
-      if (array->ElementAt(i)->mDisplayItemKey == aDisplayItemKey) {
+      DisplayItemData* data = array->ElementAt(i);
+      if (data->mDisplayItemKey == aDisplayItemKey &&
+          data->IsVisibleInLayer()) {
         return true;
       }
     }
   }
   return false;
 }
 
 void
-FrameLayerBuilder::IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback)
+FrameLayerBuilder::IterateVisibleRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback)
 {
   nsTArray<DisplayItemData*> *array = 
     reinterpret_cast<nsTArray<DisplayItemData*>*>(aFrame->Properties().Get(LayerManagerDataProperty()));
   if (!array) {
     return;
   }
   
   for (uint32_t i = 0; i < array->Length(); i++) {
     DisplayItemData* data = array->ElementAt(i);
-    if (data->mDisplayItemKey != nsDisplayItem::TYPE_ZERO) {
+    if (data->mDisplayItemKey != nsDisplayItem::TYPE_ZERO &&
+        data->IsVisibleInLayer()) {
       aCallback(aFrame, data);
     }
   }
 }
 
 FrameLayerBuilder::DisplayItemData*
 FrameLayerBuilder::GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey)
 {
@@ -1836,17 +1841,17 @@ ContainerState::ThebesLayerData::Accumul
   }
   
   bool snap;
   nsRegion opaque = aItem->GetOpaqueRegion(aState->mBuilder, &snap);
   if (!opaque.IsEmpty()) {
     nsRegion opaqueClipped;
     nsRegionRectIterator iter(opaque);
     for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
-      opaqueClipped.Or(opaqueClipped, aClip.ApproximateIntersect(*r));
+      opaqueClipped.Or(opaqueClipped, aClip.ApproximateIntersectInner(*r));
     }
 
     nsIntRegion opaquePixels = aState->ScaleRegionToInsidePixels(opaqueClipped, snap);
 
     nsIntRegionRectIterator iter2(opaquePixels);
     for (const nsIntRect* r = iter2.Next(); r; r = iter2.Next()) {
       // We don't use SimplifyInward here since it's not defined exactly
       // what it will discard. For our purposes the most important case
@@ -2343,16 +2348,17 @@ ContainerState::InvalidateForLayerChange
       ThebesLayer* newThebesLayer = aNewLayer->AsThebesLayer();
       if (newThebesLayer) {
         InvalidatePostTransformRegion(newThebesLayer,
             aGeometry->ComputeInvalidationRegion(),
             aClip,
             GetTranslationForThebesLayer(newThebesLayer));
       }
     }
+    aItem->NotifyRenderingChanged();
     return;
   } 
   if (!aNewLayer) {
     return;
   }
 
   ThebesLayer* newThebesLayer = aNewLayer->AsThebesLayer();
   if (!newThebesLayer) {
@@ -2405,16 +2411,17 @@ ContainerState::InvalidateForLayerChange
     }
 #ifdef DEBUG_INVALIDATIONS
     if (!combined.IsEmpty()) {
       printf("Display item type %s(%p) (in layer %p) changed geometry!\n", aItem->Name(), aItem->GetUnderlyingFrame(), aNewLayer);
     }
 #endif
   }
   if (!combined.IsEmpty()) {
+    aItem->NotifyRenderingChanged();
     InvalidatePostTransformRegion(newThebesLayer,
         combined.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
         GetTranslationForThebesLayer(newThebesLayer));
   }
 }
 
 void
 FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
@@ -2449,17 +2456,18 @@ FrameLayerBuilder::AddThebesDisplayItem(
 
     if (hasClip) {
       intClip = clip.GetBounds().ScaleToOutsidePixels(thebesData->mXScale, 
                                                       thebesData->mYScale, 
                                                       thebesData->mAppUnitsPerDevPixel);
     }
   }
 
-  AddLayerDisplayItem(aLayer, aItem, aClip, aLayerState, aTopLeft, tempManager, aGeometry);
+  DisplayItemData* displayItemData =
+    AddLayerDisplayItem(aLayer, aItem, aClip, aLayerState, aTopLeft, tempManager, aGeometry);
 
   ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
   if (entry) {
     entry->mContainerLayerFrame = aContainerLayerFrame;
     if (entry->mContainerLayerGeneration == 0) {
       entry->mContainerLayerGeneration = mContainerLayerGeneration;
     }
     NS_ASSERTION(aItem->GetUnderlyingFrame(), "Must have frame");
@@ -2516,17 +2524,17 @@ FrameLayerBuilder::AddThebesDisplayItem(
         }
 
         invalid.ScaleRoundOut(thebesData->mXScale, thebesData->mYScale);
         InvalidatePostTransformRegion(aLayer, invalid,
                                       GetTranslationForThebesLayer(aLayer));
       }
     }
     ClippedDisplayItem* cdi =
-      entry->mItems.AppendElement(ClippedDisplayItem(aItem, aClip,
+      entry->mItems.AppendElement(ClippedDisplayItem(aItem, displayItemData, aClip,
                                                      mContainerLayerGeneration));
     cdi->mInactiveLayerManager = tempManager;
   }
 }
 
 FrameLayerBuilder::DisplayItemData*
 FrameLayerBuilder::StoreDataForFrame(nsDisplayItem* aItem, Layer* aLayer, LayerState aState)
 {
@@ -2591,35 +2599,36 @@ FrameLayerBuilder::ClippedDisplayItem::~
     BasicLayerManager* basic = static_cast<BasicLayerManager*>(mInactiveLayerManager.get());
     if (basic->InTransaction()) {
       basic->EndTransaction(nullptr, nullptr);
     }
     basic->SetUserData(&gLayerManagerLayerBuilder, nullptr);
   }
 }
 
-void
+FrameLayerBuilder::DisplayItemData*
 FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
                                        nsDisplayItem* aItem,
                                        const Clip& aClip,
                                        LayerState aLayerState,
                                        const nsPoint& aTopLeft,
                                        LayerManager* aManager,
                                        nsAutoPtr<nsDisplayItemGeometry> aGeometry)
 {
   if (aLayer->Manager() != mRetainingManager)
-    return;
+    return nullptr;
 
   DisplayItemData *data = StoreDataForFrame(aItem, aLayer, aLayerState);
   ThebesLayer *t = aLayer->AsThebesLayer();
   if (t) {
     data->mGeometry = aGeometry;
     data->mClip = aClip;
   }
   data->mInactiveManager = aManager;
+  return data;
 }
 
 nsIntPoint
 FrameLayerBuilder::GetLastPaintOffset(ThebesLayer* aLayer)
 {
   ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
   if (entry) {
     if (entry->mContainerLayerGeneration == 0) {
@@ -3258,77 +3267,95 @@ FrameLayerBuilder::DrawThebesLayer(Thebe
   // See above for why this is OK.
   aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
   aContext->Scale(userData->mXScale, userData->mYScale);
 
   nsPresContext* presContext = containerLayerFrame->PresContext();
   int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
 
   uint32_t i;
-  // Update visible regions. We need perform visibility analysis again
-  // because we may be asked to draw into part of a ThebesLayer that
-  // isn't actually visible in the window (e.g., because a ThebesLayer
-  // expanded its visible region to a rectangle internally), in which
-  // case the mVisibleRect stored in the display item may be wrong.
-  nsRegion visible = aRegionToDraw.ToAppUnits(appUnitsPerDevPixel);
+  // Update visible rects in display items to reflect visibility
+  // just considering items in this ThebesLayer. This is different from the
+  // original visible rects, which describe which part of each item
+  // is visible in the window. These can be larger than the original
+  // visible rect, because we may be asked to draw into part of a
+  // ThebesLayer that isn't actually visible in the window (e.g.,
+  // because a ThebesLayer expanded its visible region to a rectangle
+  // internally, or because we're caching prerendered content).
+  // We also compute the intersection of those visible rects with
+  // aRegionToDraw. These are the rectangles of each display item
+  // that actually need to be drawn now.
+  // Treat as visible everything this layer already contains or will
+  // contain.
+  nsIntRegion layerRegion;
+  layerRegion.Or(aLayer->GetValidRegion(), aRegionToDraw);
+  nsRegion visible = layerRegion.ToAppUnits(appUnitsPerDevPixel);
   visible.MoveBy(NSIntPixelsToAppUnits(offset.x, appUnitsPerDevPixel),
                  NSIntPixelsToAppUnits(offset.y, appUnitsPerDevPixel));
   visible.ScaleInverseRoundOut(userData->mXScale, userData->mYScale);
+  nsRegion toDraw = aRegionToDraw.ToAppUnits(appUnitsPerDevPixel);
+  toDraw.MoveBy(NSIntPixelsToAppUnits(offset.x, appUnitsPerDevPixel),
+                NSIntPixelsToAppUnits(offset.y, appUnitsPerDevPixel));
+  toDraw.ScaleInverseRoundOut(userData->mXScale, userData->mYScale);
 
   for (i = items.Length(); i > 0; --i) {
     ClippedDisplayItem* cdi = &items[i - 1];
 
     NS_ASSERTION(AppUnitsPerDevPixel(cdi->mItem) == appUnitsPerDevPixel,
                  "a thebes layer should contain items only at the same zoom");
 
     NS_ABORT_IF_FALSE(cdi->mClip.mHaveClipRect ||
                       cdi->mClip.mRoundedClipRects.IsEmpty(),
                       "If we have rounded rects, we must have a clip rect");
 
     if (!cdi->mClip.mHaveClipRect ||
         (cdi->mClip.mRoundedClipRects.IsEmpty() &&
          cdi->mClip.mClipRect.Contains(visible.GetBounds()))) {
       cdi->mItem->RecomputeVisibility(builder, &visible);
-      continue;
-    }
-
-    // Do a little dance to account for the fact that we're clipping
-    // to cdi->mClipRect
-    nsRegion clipped;
-    clipped.And(visible, cdi->mClip.mClipRect);
-    nsRegion finalClipped = clipped;
-    cdi->mItem->RecomputeVisibility(builder, &finalClipped);
-    // If we have rounded clip rects, don't subtract from the visible
-    // region since we aren't displaying everything inside the rect.
-    if (cdi->mClip.mRoundedClipRects.IsEmpty()) {
-      nsRegion removed;
-      removed.Sub(clipped, finalClipped);
-      nsRegion newVisible;
-      newVisible.Sub(visible, removed);
-      // Don't let the visible region get too complex.
-      if (newVisible.GetNumRects() <= 15) {
-        visible = newVisible;
+    } else {
+      // Do a little dance to account for the fact that we're clipping
+      // to cdi->mClipRect
+      nsRegion clipped;
+      clipped.And(visible, cdi->mClip.mClipRect);
+      nsRegion finalClipped = clipped;
+      cdi->mItem->RecomputeVisibility(builder, &finalClipped);
+      // If we have rounded clip rects, don't subtract from the visible
+      // region since we aren't displaying everything inside the rect.
+      if (cdi->mClip.mRoundedClipRects.IsEmpty()) {
+        nsRegion removed;
+        removed.Sub(clipped, finalClipped);
+        nsRegion newVisible;
+        newVisible.Sub(visible, removed);
+        // Don't let the visible region get too complex.
+        if (newVisible.GetNumRects() <= 15) {
+          visible = newVisible;
+        }
       }
-    }
-    if (!cdi->mClip.IsRectClippedByRoundedCorner(cdi->mItem->GetVisibleRect())) {
-      cdi->mClip.RemoveRoundedCorners();
+      if (!cdi->mClip.IsRectClippedByRoundedCorner(cdi->mItem->GetVisibleRect())) {
+        cdi->mClip.RemoveRoundedCorners();
+      }
     }
   }
 
   nsRefPtr<nsRenderingContext> rc = new nsRenderingContext();
   rc->Init(presContext->DeviceContext(), aContext);
 
   Clip currentClip;
   bool setClipRect = false;
 
   for (i = 0; i < items.Length(); ++i) {
     ClippedDisplayItem* cdi = &items[i];
 
-    if (cdi->mItem->GetVisibleRect().IsEmpty())
+    if (cdi->mData) {
+      cdi->mData->SetIsVisibleInLayer(!cdi->mItem->GetVisibleRect().IsEmpty());
+    }
+
+    if (!toDraw.Intersects(cdi->mItem->GetVisibleRect())) {
       continue;
+    }
 
     // If the new desired clip state is different from the current state,
     // update the clip.
     if (setClipRect != cdi->mClip.mHaveClipRect ||
         (cdi->mClip.mHaveClipRect && cdi->mClip != currentClip)) {
       if (setClipRect) {
         aContext->Restore();
       }
@@ -3496,17 +3523,17 @@ FrameLayerBuilder::Clip::AddRoundedRectP
   clip.Round();
   clip.Condition();
 
   aContext->NewPath();
   aContext->RoundedRectangle(clip, pixelRadii);
 }
 
 nsRect
-FrameLayerBuilder::Clip::ApproximateIntersect(const nsRect& aRect) const
+FrameLayerBuilder::Clip::ApproximateIntersectInner(const nsRect& aRect) const
 {
   nsRect r = aRect;
   if (mHaveClipRect) {
     r.IntersectRect(r, mClipRect);
   }
   for (uint32_t i = 0, iEnd = mRoundedClipRects.Length();
        i < iEnd; ++i) {
     const Clip::RoundedRect &rr = mRoundedClipRects[i];
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -91,16 +91,17 @@ public:
  */
 class FrameLayerBuilder : public layers::LayerUserData {
 public:
   typedef layers::ContainerLayer ContainerLayer;
   typedef layers::Layer Layer;
   typedef layers::ThebesLayer ThebesLayer;
   typedef layers::ImageLayer ImageLayer;
   typedef layers::LayerManager LayerManager;
+  class DisplayItemData;
 
   FrameLayerBuilder() :
     mRetainingManager(nullptr),
     mDetectedDOMModification(false),
     mInvalidateAllLayers(false),
     mContainerLayerGeneration(0),
     mMaxContainerLayerGeneration(0)
   {
@@ -258,23 +259,23 @@ public:
    * @param aLayer Layer that the display item will be rendered into
    * @param aItem Display item to be drawn.
    * @param aLayerState What LayerState the item is using.
    * @param aTopLeft offset from active scrolled root to reference frame
    * @param aManager If the layer is in the LAYER_INACTIVE state,
    * then this is the temporary layer manager to draw with.
    */
   struct Clip;
-  void AddLayerDisplayItem(Layer* aLayer,
-                           nsDisplayItem* aItem,
-                           const Clip& aClip,
-                           LayerState aLayerState,
-                           const nsPoint& aTopLeft,
-                           LayerManager* aManager,
-                           nsAutoPtr<nsDisplayItemGeometry> aGeometry);
+  DisplayItemData* AddLayerDisplayItem(Layer* aLayer,
+                                       nsDisplayItem* aItem,
+                                       const Clip& aClip,
+                                       LayerState aLayerState,
+                                       const nsPoint& aTopLeft,
+                                       LayerManager* aManager,
+                                       nsAutoPtr<nsDisplayItemGeometry> aGeometry);
 
   /**
    * Record aItem as a display item that is rendered by the ThebesLayer
    * aLayer, with aClipRect, where aContainerLayerFrame is the frame
    * for the container layer this ThebesItem belongs to.
    * aItem must have an underlying frame.
    * @param aTopLeft offset from active scrolled root to reference frame
    */
@@ -309,25 +310,24 @@ public:
    * Destroy any stored LayerManagerDataProperty and the associated data for
    * aFrame.
    */
   static void DestroyDisplayItemDataFor(nsIFrame* aFrame);
 
   LayerManager* GetRetainingLayerManager() { return mRetainingManager; }
 
   /**
-   * Returns true if the given display item was rendered during the previous
-   * paint. Returns false otherwise.
+   * Returns true if the given display item was visible in its layer during
+   * the previous paint. Returns false otherwise.
    */
-  static bool HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey);
+  static bool HasVisibleRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey);
 
-  class DisplayItemData;
   typedef void (*DisplayItemDataCallback)(nsIFrame *aFrame, DisplayItemData* aItem);
 
-  static void IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback);
+  static void IterateVisibleRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback);
 
   /**
    * Save transform that was in aLayer when we last painted, and the position
    * of the active scrolled root frame. It must be an integer
    * translation.
    */
   void SaveLastPaintOffset(ThebesLayer* aLayer);
   /**
@@ -412,17 +412,17 @@ public:
                             uint32_t aBegin, uint32_t aEnd) const;
     // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext
     void AddRoundedRectPathTo(gfxContext* aContext, int32_t A2D,
                               const RoundedRect &aRoundRect) const;
 
     // Return a rectangle contained in the intersection of aRect with this
     // clip region. Tries to return the largest possible rectangle, but may
     // not succeed.
-    nsRect ApproximateIntersect(const nsRect& aRect) const;
+    nsRect ApproximateIntersectInner(const nsRect& aRect) const;
 
     // Returns false if aRect is definitely not clipped by a rounded corner in
     // this clip. Returns true if aRect is clipped by a rounded corner in this
     // clip or it can not be quickly determined that it is not clipped by a
     // rounded corner in this clip.
     bool IsRectClippedByRoundedCorner(const nsRect& aRect) const;
 
     // Intersection of all rects in this clip ignoring any rounded corners.
@@ -472,16 +472,19 @@ public:
    */
   class DisplayItemData {
   public:
     friend class FrameLayerBuilder;
 
     uint32_t GetDisplayItemKey() { return mDisplayItemKey; }
     Layer* GetLayer() { return mLayer; }
     void Invalidate() { mIsInvalid = true; }
+    bool IsVisibleInLayer() { return mIsVisible; }
+    void SetIsVisibleInLayer(bool aIsVisible) { mIsVisible = aIsVisible; }
+
   protected:
 
     DisplayItemData(LayerManagerData* aParent, uint32_t aKey, Layer* aLayer, LayerState aLayerState, uint32_t aGeneration);
     DisplayItemData(DisplayItemData &toCopy);
 
     /**
      * Removes any references to this object from frames
      * in mFrameList.
@@ -520,17 +523,25 @@ public:
     uint32_t        mContainerLayerGeneration;
     LayerState      mLayerState;
 
     /**
      * Used to track if data currently stored in mFramesWithLayers (from an existing
      * paint) has been updated in the current paint.
      */
     bool            mUsed;
+    /**
+     * True if the entire display item needs to be invalidated.
+     */
     bool            mIsInvalid;
+    /**
+     * True if the display item is visible in its layer, otherwise
+     * it's completely covered by opaque content in its ThebesLayer.
+     */
+    bool            mIsVisible;
   };
 
 protected:
 
   friend class LayerManagerData;
 
   static void RemoveFrameFromLayerManager(nsIFrame* aFrame, void* aPropertyValue);
 
@@ -587,24 +598,27 @@ protected:
    * of ClippedDisplayItems. (ThebesLayerItemsEntry is the hash entry
    * for that hashtable.)
    * These are only stored during the paint process, so that the
    * DrawThebesLayer callback can figure out which items to draw for the
    * ThebesLayer.
    * mItem always has an underlying frame.
    */
   struct ClippedDisplayItem {
-    ClippedDisplayItem(nsDisplayItem* aItem, const Clip& aClip, uint32_t aGeneration)
-      : mItem(aItem), mClip(aClip), mContainerLayerGeneration(aGeneration)
+    ClippedDisplayItem(nsDisplayItem* aItem, DisplayItemData* aData,
+                       const Clip& aClip, uint32_t aGeneration)
+      : mItem(aItem), mData(aData), mClip(aClip),
+        mContainerLayerGeneration(aGeneration)
     {
     }
 
     ~ClippedDisplayItem();
 
     nsDisplayItem* mItem;
+    DisplayItemData* mData;
 
     /**
      * If the display item is being rendered as an inactive
      * layer, then this stores the layer manager being
      * used for the inactive transaction.
      */
     nsRefPtr<LayerManager> mInactiveLayerManager;
 
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -104,49 +104,53 @@ CollectRestyles(nsISupports* aElement,
   *restyleArrayPtr = currentRestyle + 1;
 
   return PL_DHASH_NEXT;
 }
 
 inline void
 RestyleTracker::ProcessOneRestyle(Element* aElement,
                                   nsRestyleHint aRestyleHint,
-                                  nsChangeHint aChangeHint)
+                                  nsChangeHint aChangeHint,
+                                  OverflowChangedTracker& aTracker)
 {
   NS_PRECONDITION((aRestyleHint & eRestyle_LaterSiblings) == 0,
                   "Someone should have handled this before calling us");
   NS_PRECONDITION(Document(), "Must have a document");
   NS_PRECONDITION(aElement->GetCurrentDoc() == Document(),
                   "Element has unexpected document");
 
   nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
   if (aRestyleHint & (eRestyle_Self | eRestyle_Subtree)) {
     mFrameConstructor->RestyleElement(aElement, primaryFrame, aChangeHint,
                                       *this,
-                                      (aRestyleHint & eRestyle_Subtree) != 0);
+                                      (aRestyleHint & eRestyle_Subtree) != 0, 
+                                      aTracker);
   } else if (aChangeHint &&
              (primaryFrame ||
               (aChangeHint & nsChangeHint_ReconstructFrame))) {
     // Don't need to recompute style; just apply the hint
     nsStyleChangeList changeList;
     changeList.AppendChange(primaryFrame, aElement, aChangeHint);
-    mFrameConstructor->ProcessRestyledFrames(changeList);
+    mFrameConstructor->ProcessRestyledFrames(changeList, aTracker);
   }
 }
 
 void
 RestyleTracker::DoProcessRestyles()
 {
   SAMPLE_LABEL("CSS", "ProcessRestyles");
   // Make sure to not rebuild quote or counter lists while we're
   // processing restyles
   mFrameConstructor->BeginUpdate();
 
   mFrameConstructor->mInStyleRefresh = true;
 
+  OverflowChangedTracker tracker;
+
   // loop so that we process any restyle events generated by processing
   while (mPendingRestyles.Count()) {
     if (mHaveLaterSiblingRestyles) {
       // Convert them to individual restyles on all the later siblings
       nsAutoTArray<nsRefPtr<Element>, RESTYLE_ARRAY_STACKSIZE> laterSiblingArr;
       LaterSiblingCollector siblingCollector = { this, &laterSiblingArr };
       mPendingRestyles.Enumerate(CollectLaterSiblings, &siblingCollector);
       for (uint32_t i = 0; i < laterSiblingArr.Length(); ++i) {
@@ -201,17 +205,17 @@ RestyleTracker::DoProcessRestyles()
         continue;
       }
 
       RestyleData data;
       if (!GetRestyleData(element, &data)) {
         continue;
       }
 
-      ProcessOneRestyle(element, data.mRestyleHint, data.mChangeHint);
+      ProcessOneRestyle(element, data.mRestyleHint, data.mChangeHint, tracker);
     }
 
     if (mHaveLaterSiblingRestyles) {
       // Keep processing restyles for now
       continue;
     }
 
     // Now we only have entries with change hints left.  To be safe in
@@ -230,21 +234,24 @@ RestyleTracker::DoProcessRestyles()
       // Clear the hashtable now that we don't need it anymore
       mPendingRestyles.Clear();
 
       for (RestyleEnumerateData* currentRestyle = restylesToProcess;
            currentRestyle != lastRestyle;
            ++currentRestyle) {
         ProcessOneRestyle(currentRestyle->mElement,
                           currentRestyle->mRestyleHint,
-                          currentRestyle->mChangeHint);
+                          currentRestyle->mChangeHint,
+                          tracker);
       }
     }
   }
 
+  tracker.Flush();
+
   // Set mInStyleRefresh to false now, since the EndUpdate call might
   // add more restyles.
   mFrameConstructor->mInStyleRefresh = false;
 
   mFrameConstructor->EndUpdate();
 
 #ifdef DEBUG
   mFrameConstructor->mPresShell->VerifyStyleTree();
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -9,22 +9,146 @@
  */
 
 #ifndef mozilla_css_RestyleTracker_h
 #define mozilla_css_RestyleTracker_h
 
 #include "mozilla/dom/Element.h"
 #include "nsDataHashtable.h"
 #include "nsIFrame.h"
+#include "nsTPriorityQueue.h"
 
 class nsCSSFrameConstructor;
 
 namespace mozilla {
 namespace css {
 
+/** 
+ * Helper class that collects a list of frames that need
+ * UpdateOverflow() called on them, and coalesces them
+ * to avoid walking up the same ancestor tree multiple times.
+ */
+class OverflowChangedTracker
+{
+public:
+
+  /**
+   * Add a frame that has had a style change, and needs its
+   * overflow updated.
+   *
+   * If there are pre-transform overflow areas stored for this
+   * frame, then we will call FinishAndStoreOverflow with those
+   * areas instead of UpdateOverflow().
+   *
+   * If the overflow area changes, then UpdateOverflow will also
+   * be called on the parent.
+   */
+  void AddFrame(nsIFrame* aFrame) {
+    mEntryList.Push(Entry(aFrame, true));
+  }
+
+  /**
+   * Update the overflow of all added frames, and clear the entry list.
+   *
+   * Start from those deepest in the frame tree and works upwards. This stops 
+   * us from processing the same frame twice.
+   */
+  void Flush() {
+    while (!mEntryList.IsEmpty()) {
+      Entry entry = mEntryList.Pop();
+
+      // Pop off any duplicate entries and copy back mInitial
+      // if any have it set.
+      while (!mEntryList.IsEmpty() &&
+             mEntryList.Top().mFrame == entry.mFrame) {
+        Entry next = mEntryList.Pop();
+
+        if (next.mInitial) {
+          entry.mInitial = true;
+        }
+      }
+      nsIFrame *frame = entry.mFrame;
+
+      bool updateParent = false;
+      if (entry.mInitial) {
+        nsOverflowAreas* pre = static_cast<nsOverflowAreas*>
+          (frame->Properties().Get(frame->PreTransformOverflowAreasProperty()));
+        if (pre) {
+          // FinishAndStoreOverflow will change the overflow areas passed in,
+          // so make a copy.
+          nsOverflowAreas overflowAreas = *pre;
+          frame->FinishAndStoreOverflow(overflowAreas, frame->GetSize());
+          // We can't tell if the overflow changed, so update the parent regardless
+          updateParent = true;
+        }
+      }
+      
+      // If the overflow changed, then we want to also update the parent's
+      // overflow. We always update the parent for initial frames.
+      if (!updateParent) {
+        updateParent = frame->UpdateOverflow() || entry.mInitial;
+      }
+      if (updateParent) {
+        nsIFrame *parent = frame->GetParent();
+        if (parent) {
+          mEntryList.Push(Entry(parent, entry.mDepth - 1, false));
+        }
+      }
+    }
+  }
+  
+private:
+  struct Entry
+  {
+    Entry(nsIFrame* aFrame, bool aInitial)
+      : mFrame(aFrame)
+      , mDepth(aFrame->GetDepthInFrameTree())
+      , mInitial(aInitial)
+    {}
+    
+    Entry(nsIFrame* aFrame, uint32_t aDepth, bool aInitial)
+      : mFrame(aFrame)
+      , mDepth(aDepth)
+      , mInitial(aInitial)
+    {}
+
+    bool operator==(const Entry& aOther) const
+    {
+      return mFrame == aOther.mFrame;
+    }
+ 
+    /**
+     * Sort by the depth in the frame tree, and then
+     * the frame pointer.
+     */
+    bool operator<(const Entry& aOther) const
+    {
+      if (mDepth != aOther.mDepth) {
+        // nsTPriorityQueue implements a min-heap and we
+        // want the highest depth first, so reverse this check.
+        return mDepth > aOther.mDepth;
+      }
+
+      return mFrame < aOther.mFrame;
+    }
+
+    nsIFrame* mFrame;
+    /* Depth in the frame tree */
+    uint32_t mDepth;
+    /**
+     * True if the frame had the actual style change, and we
+     * want to check for pre-transform overflow areas.
+     */
+    bool mInitial;
+  };
+
+  /* A list of frames to process, sorted by their depth in the frame tree */
+  nsTPriorityQueue<Entry> mEntryList;
+};
+
 class RestyleTracker {
 public:
   typedef mozilla::dom::Element Element;
 
   RestyleTracker(uint32_t aRestyleBits,
                  nsCSSFrameConstructor* aFrameConstructor) :
     mRestyleBits(aRestyleBits), mFrameConstructor(aFrameConstructor),
     mHaveLaterSiblingRestyles(false)
@@ -109,17 +233,18 @@ public:
 private:
   /**
    * Handle a single mPendingRestyles entry.  aRestyleHint must not
    * include eRestyle_LaterSiblings; that needs to be dealt with
    * before calling this function.
    */
   inline void ProcessOneRestyle(Element* aElement,
                                 nsRestyleHint aRestyleHint,
-                                nsChangeHint aChangeHint);
+                                nsChangeHint aChangeHint,
+                                OverflowChangedTracker& aTracker);
 
   /**
    * The guts of our restyle processing.
    */
   void DoProcessRestyles();
 
   typedef nsDataHashtable<nsISupportsHashKey, RestyleData> PendingRestyleTable;
   typedef nsAutoTArray< nsRefPtr<Element>, 32> RestyleRootArray;
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -7759,17 +7759,16 @@ DoApplyRenderingChangeToTree(nsIFrame* a
     if (aChange & nsChangeHint_UpdateOpacityLayer) {
       // FIXME/bug 796697: we can get away with empty transactions for
       // opacity updates in many cases.
       needInvalidatingPaint = true;
       aFrame->MarkLayersActive(nsChangeHint_UpdateOpacityLayer);
     }
     if (aChange & nsChangeHint_UpdateTransformLayer) {
       aFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
-      aFrame->AddStateBits(NS_FRAME_TRANSFORM_CHANGED);
       // If we're not already going to do an invalidating paint, see
       // if we can get away with only updating the transform on a
       // layer for this frame, and not scheduling an invalidating
       // paint.
       if (!needInvalidatingPaint) {
         needInvalidatingPaint |= !aFrame->TryUpdateTransformOnly();
       }
     }
@@ -8052,17 +8051,18 @@ NeedToReframeForAddingOrRemovingTransfor
     if (FrameHasPositionedPlaceholderDescendants(f, positionMask)) {
       return true;
     }
   }
   return false;
 }
 
 nsresult
-nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
+nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList,
+                                             OverflowChangedTracker& aTracker)
 {
   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                "Someone forgot a script blocker");
   int32_t count = aChangeList.Count();
   if (!count)
     return NS_OK;
 
   SAMPLE_LABEL("CSS", "ProcessRestyledFrames");
@@ -8204,40 +8204,20 @@ nsCSSFrameConstructor::ProcessRestyledFr
                          "SVG child frame not expected to have different parent");
           }
         }
         // If |frame| is dirty or has dirty children, we don't bother updating
         // overflows since that will happen when it's reflowed.
         if (!(frame->GetStateBits() &
               (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
           while (frame) {
-            nsOverflowAreas* pre = static_cast<nsOverflowAreas*>
-              (frame->Properties().Get(frame->PreTransformOverflowAreasProperty()));
-            if (pre) {
-              // FinishAndStoreOverflow will change the overflow areas passed in,
-              // so make a copy.
-              nsOverflowAreas overflowAreas = *pre;
-              frame->FinishAndStoreOverflow(overflowAreas, frame->GetSize());
-            } else {
-              frame->UpdateOverflow();
-            }
-
-            nsIFrame* next =
+            aTracker.AddFrame(frame);
+
+            frame =
               nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame);
-            // Update the ancestors' overflow after we have updated the overflow
-            // for all the continuations with the same parent.
-            if (!next || frame->GetParent() != next->GetParent()) {
-              for (nsIFrame* ancestor = frame->GetParent(); ancestor;
-                   ancestor = ancestor->GetParent()) {
-                if (!ancestor->UpdateOverflow()) {
-                  break;
-                }
-              }
-            }
-            frame = next;
           }
         }
       }
       if (hint & nsChangeHint_UpdateCursor) {
         mPresShell->SynthesizeMouseMove(false);
       }
     }
   }
@@ -8272,17 +8252,18 @@ nsCSSFrameConstructor::ProcessRestyledFr
   return NS_OK;
 }
 
 void
 nsCSSFrameConstructor::RestyleElement(Element        *aElement,
                                       nsIFrame       *aPrimaryFrame,
                                       nsChangeHint   aMinHint,
                                       RestyleTracker& aRestyleTracker,
-                                      bool            aRestyleDescendants)
+                                      bool            aRestyleDescendants,
+                                      OverflowChangedTracker& aTracker)
 {
   NS_ASSERTION(aPrimaryFrame == aElement->GetPrimaryFrame(),
                "frame/content mismatch");
   if (aPrimaryFrame && aPrimaryFrame->GetContent() != aElement) {
     // XXXbz this is due to image maps messing with the primary frame pointer
     // of <area>s.  See bug 135040.  We can remove this block once that's fixed.
     aPrimaryFrame = nullptr;
   }
@@ -8309,17 +8290,17 @@ nsCSSFrameConstructor::RestyleElement(El
   }
 
   if (aMinHint & nsChangeHint_ReconstructFrame) {
     RecreateFramesForContent(aElement, false);
   } else if (aPrimaryFrame) {
     nsStyleChangeList changeList;
     ComputeStyleChangeFor(aPrimaryFrame, &changeList, aMinHint,
                           aRestyleTracker, aRestyleDescendants);
-    ProcessRestyledFrames(changeList);
+    ProcessRestyledFrames(changeList, aTracker);
   } else {
     // no frames, reconstruct for content
     MaybeRecreateFramesForElement(aElement);
   }
 }
 
 nsresult
 nsCSSFrameConstructor::ContentStateChanged(nsIContent* aContent,
@@ -12064,17 +12045,19 @@ nsCSSFrameConstructor::DoRebuildAllStyle
   nsStyleChangeList changeList;
   // XXX Does it matter that we're passing aExtraHint to the real root
   // frame and not the root node's primary frame?
   // Note: The restyle tracker we pass in here doesn't matter.
   ComputeStyleChangeFor(mPresShell->GetRootFrame(),
                         &changeList, aExtraHint,
                         aRestyleTracker, true);
   // Process the required changes
-  ProcessRestyledFrames(changeList);
+  OverflowChangedTracker tracker;
+  ProcessRestyledFrames(changeList, tracker);
+  tracker.Flush();
 
   // Tell the style set it's safe to destroy the old rule tree.  We
   // must do this after the ProcessRestyledFrames call in case the
   // change list has frame reconstructs in it (since frames to be
   // reconstructed will still have their old style context pointers
   // until they are destroyed).
   mPresShell->StyleSet()->EndReconstruct();
 }
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -48,16 +48,17 @@ class nsFrameConstructorSaveState;
 
 class nsCSSFrameConstructor : public nsFrameManager
 {
   friend class nsRefreshDriver;
 
 public:
   typedef mozilla::dom::Element Element;
   typedef mozilla::css::RestyleTracker RestyleTracker;
+  typedef mozilla::css::OverflowChangedTracker OverflowChangedTracker;
 
   nsCSSFrameConstructor(nsIDocument *aDocument, nsIPresShell* aPresShell);
   ~nsCSSFrameConstructor(void) {
     NS_ASSERTION(mUpdateCount == 0, "Dying in the middle of our own update?");
   }
 
   struct RestyleData;
   friend struct RestyleData;
@@ -231,17 +232,18 @@ public:
   // as a result of a change to the :hover content state.
   uint32_t GetHoverGeneration() const { return mHoverGeneration; }
 
   // Note: It's the caller's responsibility to make sure to wrap a
   // ProcessRestyledFrames call in a view update batch and a script blocker.
   // This function does not call ProcessAttachedQueue() on the binding manager.
   // If the caller wants that to happen synchronously, it needs to handle that
   // itself.
-  nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray);
+  nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray,
+                                 OverflowChangedTracker& aTracker);
 
 private:
 
   friend class mozilla::css::RestyleTracker;
 
   void RestyleForEmptyChange(Element* aContainer);
 
 public:
@@ -385,17 +387,18 @@ private:
                               nsIFrame*&     aCanvasFrame);
 
   /* aMinHint is the minimal change that should be made to the element */
   // XXXbz do we really need the aPrimaryFrame argument here?
   void RestyleElement(Element* aElement,
                       nsIFrame*       aPrimaryFrame,
                       nsChangeHint    aMinHint,
                       RestyleTracker& aRestyleTracker,
-                      bool            aRestyleDescendants);
+                      bool            aRestyleDescendants,
+                      OverflowChangedTracker& aTracker);
 
   nsresult InitAndRestoreFrame (const nsFrameConstructorState& aState,
                                 nsIContent*                    aContent,
                                 nsIFrame*                      aParentFrame,
                                 nsIFrame*                      aPrevInFlow,
                                 nsIFrame*                      aNewFrame,
                                 bool                           aAllowCounters = true);
 
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -2840,17 +2840,18 @@ nsCSSRendering::ComputeBackgroundPositio
       NS_ASSERTION(aLayer.mOrigin == NS_STYLE_BG_ORIGIN_CONTENT,
                    "unknown background-origin value");
     }
     geometryFrame->ApplySkipSides(border);
     bgPositioningArea.Deflate(border);
   }
 
   nsIFrame* attachedToFrame = aForFrame;
-  if (NS_STYLE_BG_ATTACHMENT_FIXED == aLayer.mAttachment) {
+  if (NS_STYLE_BG_ATTACHMENT_FIXED == aLayer.mAttachment &&
+      !aLayer.mImage.IsEmpty()) {
     // If it's a fixed background attachment, then the image is placed
     // relative to the viewport, which is the area of the root frame
     // in a screen context or the page content frame in a print context.
     attachedToFrame = aPresContext->PresShell()->FrameManager()->GetRootFrame();
     NS_ASSERTION(attachedToFrame, "no root frame");
     nsIFrame* pageContentFrame = nullptr;
     if (aPresContext->IsPaginated()) {
       pageContentFrame =
@@ -4684,36 +4685,29 @@ nsImageRenderer::Draw(nsPresContext*    
     default:
       break;
   }
 }
 
 bool
 nsImageRenderer::IsRasterImage()
 {
-  if (mType != eStyleImageType_Image)
+  if (mType != eStyleImageType_Image || !mImageContainer)
     return false;
-  nsCOMPtr<imgIContainer> img;
-  if (NS_FAILED(mImage->GetImageData()->GetImage(getter_AddRefs(img))))
-    return false;
-  return img->GetType() == imgIContainer::TYPE_RASTER;
+  return mImageContainer->GetType() == imgIContainer::TYPE_RASTER;
 }
 
 already_AddRefed<mozilla::layers::ImageContainer>
 nsImageRenderer::GetContainer(LayerManager* aManager)
 {
-  if (mType != eStyleImageType_Image)
-    return nullptr;
-  nsCOMPtr<imgIContainer> img;
-  nsresult rv = mImage->GetImageData()->GetImage(getter_AddRefs(img));
-  if (NS_FAILED(rv))
+  if (mType != eStyleImageType_Image || !mImageContainer)
     return nullptr;
 
   nsRefPtr<ImageContainer> container;
-  rv = img->GetImageContainer(aManager, getter_AddRefs(container));
+  nsresult rv = mImageContainer->GetImageContainer(aManager, getter_AddRefs(container));
   NS_ENSURE_SUCCESS(rv, nullptr);
   return container.forget();
 }
 
 #define MAX_BLUR_RADIUS 300
 #define MAX_SPREAD_RADIUS 50
 
 static inline gfxIntSize
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -850,17 +850,27 @@ public:
   {
     const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
     bool snap;
     if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
         !geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
       aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
     }
   }
-  
+
+  /**
+   * Called when the area rendered by this display item has changed (been
+   * invalidated or changed geometry) since the last paint. This includes
+   * when the display item was not rendered at all in the last paint.
+   * It does NOT get called when a display item was being rendered and no
+   * longer is, because generally that means there is no display item to
+   * call this method on.
+   */
+  virtual void NotifyRenderingChanged() {}
+
   /**
    * @param aSnap set to true if the edges of the rectangles of the opaque
    * region would be snapped to device pixels when drawing
    * @return a region of the item that is opaque --- that is, every pixel
    * that is visible (according to ComputeVisibility) is painted with an opaque
    * color. This is useful for determining when one piece
    * of content completely obscures another so that we can do occlusion
    * culling.
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -2720,17 +2720,19 @@ PresShell::RecreateFramesFor(nsIContent*
 
   nsAutoScriptBlocker scriptBlocker;
 
   nsStyleChangeList changeList;
   changeList.AppendChange(nullptr, aContent, nsChangeHint_ReconstructFrame);
 
   // Mark ourselves as not safe to flush while we're doing frame construction.
   ++mChangeNestCount;
-  nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList);
+  css::OverflowChangedTracker tracker;
+  nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList, tracker);
+  tracker.Flush();
   --mChangeNestCount;
   
   return rv;
 }
 
 void
 nsIPresShell::PostRecreateFramesFor(Element* aElement)
 {
@@ -7835,17 +7837,19 @@ PresShell::Observe(nsISupports* aSubject
         nsStyleChangeList changeList;
         WalkFramesThroughPlaceholders(mPresContext, rootFrame,
                                       ReframeImageBoxes, &changeList);
         // Mark ourselves as not safe to flush while we're doing frame
         // construction.
         {
           nsAutoScriptBlocker scriptBlocker;
           ++mChangeNestCount;
-          mFrameConstructor->ProcessRestyledFrames(changeList);
+          css::OverflowChangedTracker tracker;
+          mFrameConstructor->ProcessRestyledFrames(changeList, tracker);
+          tracker.Flush();
           --mChangeNestCount;
         }
       }
     }
     return NS_OK;
   }
 #endif
 
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -20,19 +20,17 @@
 #include "nsIDocument.h"
 #include "nsGUIEvent.h"
 #include "nsEventDispatcher.h"
 #include "jsapi.h"
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 #include "nsIViewManager.h"
 #include "sampler.h"
-
-using mozilla::TimeStamp;
-using mozilla::TimeDuration;
+#include "nsNPAPIPluginInstance.h"
 
 using namespace mozilla;
 
 #define DEFAULT_FRAME_RATE 60
 #define DEFAULT_THROTTLED_FRAME_RATE 1
 
 static bool sPrecisePref;
 
@@ -305,16 +303,21 @@ NS_IMETHODIMP
 nsRefreshDriver::Notify(nsITimer *aTimer)
 {
   SAMPLE_LABEL("nsRefreshDriver", "Notify");
 
   NS_PRECONDITION(!mFrozen, "Why are we notified while frozen?");
   NS_PRECONDITION(mPresContext, "Why are we notified after disconnection?");
   NS_PRECONDITION(!nsContentUtils::GetCurrentJSContext(),
                   "Shouldn't have a JSContext on the stack");
+  if (nsNPAPIPluginInstance::InPluginCall()) {
+    NS_ERROR("Refresh driver should not run during plugin call!");
+    // Try to survive this by just ignoring the refresh tick.
+    return NS_OK;
+  }
 
   if (mTestControllingRefreshes && aTimer) {
     // Ignore real refreshes from our timer (but honor the others).
     return NS_OK;
   }
 
   UpdateMostRecentRefresh();
 
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -234,17 +234,16 @@ nsDisplayCanvasBackground::Paint(nsDispl
                                   surf ? bounds : mVisibleRect,
                                   nsRect(offset, mFrame->GetSize()),
                                   aBuilder->GetBackgroundPaintFlags(),
                                   &bgClipRect, mLayer);
   if (surf) {
     BlitSurface(dest, destRect, surf);
 
     GetUnderlyingFrame()->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().get());
-    GetUnderlyingFrame()->AddStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);
   }
 }
 
 /**
  * A display item to paint the focus ring for the document.
  *
  * The only reason this can't use nsDisplayGeneric is overriding GetBounds.
  */
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -176,16 +176,20 @@ public:
     // Put background-attachment:fixed canvas background images in their own
     // compositing layer. Since we know their background painting area can't
     // change (unless the viewport size itself changes), async scrolling
     // will work well.
     return mBackgroundStyle &&
       mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
       !mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty();
   }
+  virtual void NotifyRenderingChanged() MOZ_OVERRIDE
+  {
+    mFrame->Properties().Delete(nsIFrame::CachedBackgroundImage());
+  }
 
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) MOZ_OVERRIDE;
  
   // We still need to paint a background color as well as an image for this item, 
   // so we can't support this yet.
   virtual bool SupportsOptimizingToImage() { return false; }
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4862,27 +4862,23 @@ static void InvalidateFrameInternal(nsIF
   }
   if (!parent || needsSchedulePaint) {
     aFrame->SchedulePaint();
   }
   if (aFrame->HasAnyStateBits(NS_FRAME_HAS_INVALID_RECT)) {
     aFrame->Properties().Delete(nsIFrame::InvalidationRect());
     aFrame->RemoveStateBits(NS_FRAME_HAS_INVALID_RECT);
   }
-  if (aFrame->HasAnyStateBits(NS_FRAME_HAS_CACHED_BACKGROUND)) {
-    aFrame->Properties().Delete(nsIFrame::CachedBackgroundImage());
-    aFrame->RemoveStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);
-  }
 }
 
 void
 nsIFrame::InvalidateFrameSubtree(uint32_t aDisplayItemKey)
 {
   bool hasDisplayItem = 
-    !aDisplayItemKey || FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey);
+    !aDisplayItemKey || FrameLayerBuilder::HasVisibleRetainedDataFor(this, aDisplayItemKey);
   InvalidateFrame(aDisplayItemKey);
 
   if (HasAnyStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT) || !hasDisplayItem) {
     return;
   }
 
   AddStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT);
   
@@ -4918,25 +4914,25 @@ nsIFrame::ClearInvalidationStateBits()
                   NS_FRAME_DESCENDANT_NEEDS_PAINT | 
                   NS_FRAME_ALL_DESCENDANTS_NEED_PAINT);
 }
 
 void
 nsIFrame::InvalidateFrame(uint32_t aDisplayItemKey)
 {
   bool hasDisplayItem = 
-    !aDisplayItemKey || FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey);
+    !aDisplayItemKey || FrameLayerBuilder::HasVisibleRetainedDataFor(this, aDisplayItemKey);
   InvalidateFrameInternal(this, hasDisplayItem);
 }
 
 void
 nsIFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
 {
   bool hasDisplayItem = 
-    !aDisplayItemKey || FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey);
+    !aDisplayItemKey || FrameLayerBuilder::HasVisibleRetainedDataFor(this, aDisplayItemKey);
   bool alreadyInvalid = false;
   if (!HasAnyStateBits(NS_FRAME_NEEDS_PAINT)) {
     InvalidateFrameInternal(this, hasDisplayItem);
   } else {
     alreadyInvalid = true;
   } 
 
   if (!hasDisplayItem) {
@@ -7015,30 +7011,28 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
      * ensured us we'll use.
      */
     nsRect newBounds(nsPoint(0, 0), aNewSize);
     // Transform affects both overflow areas.
     NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
       nsRect& o = aOverflowAreas.Overflow(otype);
       o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds);
     }
-    if ((sizeChanged || HasAnyStateBits(NS_FRAME_TRANSFORM_CHANGED)) && Preserves3DChildren()) {
+    if (Preserves3DChildren()) {
       ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
     } else if (sizeChanged && ChildrenHavePerspective()) {
       RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
     }
   } else {
     Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
     if (ChildrenHavePerspective() && sizeChanged) {
       nsRect newBounds(nsPoint(0, 0), aNewSize);
       RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
     }
   }
-  RemoveStateBits(NS_FRAME_TRANSFORM_CHANGED);
-    
 
   bool anyOverflowChanged;
   if (aOverflowAreas != nsOverflowAreas(bounds, bounds)) {
     anyOverflowChanged = SetOverflowAreas(aOverflowAreas);
   } else {
     anyOverflowChanged = ClearOverflowRects();
   }
 
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -248,20 +248,16 @@ typedef uint64_t nsFrameState;
 // TEXT_FORCE_TRIM_WHITESPACE.  That's OK because we only check the
 // NS_FRAME_IS_PUSHED_FLOAT bit on frames which we already know are
 // out-of-flow.
 #define NS_FRAME_IS_PUSHED_FLOAT                    NS_FRAME_STATE_BIT(32)
 
 // This bit acts as a loop flag for recursive paint server drawing.
 #define NS_FRAME_DRAWING_AS_PAINTSERVER             NS_FRAME_STATE_BIT(33)
 
-// Marks the frame as having a changed transform between processing
-// nsChangeHint_UpdateTransformLayer and calling FinishAndStoreOverflow.
-#define NS_FRAME_TRANSFORM_CHANGED                  NS_FRAME_STATE_BIT(34)
-
 // Frame is a display root and the retained layer tree needs to be updated
 // at the next paint via display list construction.
 // Only meaningful for display roots, so we don't really need a global state
 // bit; we could free up this bit with a little extra complexity.
 #define NS_FRAME_UPDATE_LAYER_TREE                  NS_FRAME_STATE_BIT(36)
 
 // Frame can accept absolutely positioned children.
 #define NS_FRAME_HAS_ABSPOS_CHILDREN                NS_FRAME_STATE_BIT(37)
@@ -295,20 +291,16 @@ typedef uint64_t nsFrameState;
 // Is this frame allowed to have generated (::before/::after) content?
 #define NS_FRAME_MAY_HAVE_GENERATED_CONTENT         NS_FRAME_STATE_BIT(44)
 
 // This bit is set on frames that create ContainerLayers with component
 // alpha children. With BasicLayers we avoid creating these, so we mark
 // the frames for future reference.
 #define NS_FRAME_NO_COMPONENT_ALPHA                 NS_FRAME_STATE_BIT(45)
 
-// Frame has a cached rasterization of anV
-// nsDisplayBackground display item
-#define NS_FRAME_HAS_CACHED_BACKGROUND              NS_FRAME_STATE_BIT(46)
-
 // The frame is a descendant of nsSVGTextFrame2 and is thus used for SVG
 // text layout.
 #define NS_FRAME_IS_SVG_TEXT                        NS_FRAME_STATE_BIT(47)
 
 // Frame is marked as needing painting
 #define NS_FRAME_NEEDS_PAINT                        NS_FRAME_STATE_BIT(48)
 
 // Frame has a descendant frame that needs painting - This includes
@@ -1310,16 +1302,28 @@ public:
   bool ChildrenHavePerspective() const;
 
   // Calculate the overflow size of all child frames, taking preserve-3d into account
   void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
 
   void RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds);
 
   /**
+   * Returns the number of ancestors between this and the root of our frame tree
+   */
+  uint32_t GetDepthInFrameTree() {
+    uint32_t result = 0;
+    for (nsIFrame* ancestor = GetParent(); ancestor;
+         ancestor = ancestor->GetParent()) {
+      result++;
+    }
+    return result;
+  }
+
+  /**
    * Event handling of GUI events.
    *
    * @param   aEvent event structure describing the type of event and rge widget
    *            where the event originated
    *          The |point| member of this is in the coordinate system of the
    *          view returned by GetOffsetFromView.
    * @param   aEventStatus a return value indicating whether the event was handled
    *            and whether default processing should be done
--- a/layout/mathml/nsMathMLmactionFrame.h
+++ b/layout/mathml/nsMathMLmactionFrame.h
@@ -61,17 +61,17 @@ private:
   void MouseOver();
   void MouseOut();
 
   class MouseListener MOZ_FINAL : public nsIDOMEventListener
   {
     NS_DECL_ISUPPORTS
     NS_DECL_NSIDOMEVENTLISTENER
 
-    MouseListener(nsMathMLmactionFrame* aOwner) : mOwner(aOwner) { };
+    MouseListener(nsMathMLmactionFrame* aOwner) : mOwner(aOwner) { }
 
     nsMathMLmactionFrame* mOwner;
   };
 
 protected:
   nsMathMLmactionFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {}
   virtual ~nsMathMLmactionFrame();
   
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bidi/dirAuto/bdi-auto-dir-default-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>HTML Test: BDI: paragraph-level container</title>
+    <link rel="reference" href="bdi-auto-dir-default-ref.html">
+    <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+    <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+    <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#the-bdi-element">
+    <meta name="assert" content="
+      'The dir global attribute defaults to auto on this element (it never inherits from the parent
+      element like with other elements).'">
+    <style>
+      body{
+        font-size:2em;
+      }
+      .box {
+        border: medium solid gray;
+        width: 500px;
+        margin: 20px;
+      }
+    </style>
+  </head>
+  <body>
+    <!-- Key to entities used below:
+      &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+      &#x202D; - The LRO (left-to-right-override) formatting character.
+      &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO. -->
+    <div class="box">
+      <div dir="ltr">&#x202D;[:)], [+- a &#x05D1;], [d &#x05D2; 1]...&#x202C;</div>
+      <div dir="rtl">&#x202D;...[d &#x05D2; 1] ,[+- a &#x05D1;] ,[:)]&#x202C;</div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bidi/dirAuto/bdi-auto-dir-default.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>HTML Test: BDI: paragraph-level container</title>
+    <link rel="reference" href="bdi-auto-dir-default-ref.html">
+    <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+    <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+    <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#the-bdi-element">
+    <meta name="assert" content="
+      'The dir global attribute defaults to auto on this element (it never inherits from the parent
+      element like with other elements).'">
+    <style>
+      body{
+        font-size:2em;
+      }
+      .box {
+        border: medium solid gray;
+        width: 500px;
+        margin: 20px;
+      }
+    </style>
+  </head>
+  <body>
+    <!-- Key to entities used below:
+      &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+      &#x202D; - The LRO (left-to-right-override) formatting character.
+      &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO. -->
+    <div class="box">
+      <!--
+        In each DIV below:
+        - the first BDI, having no characters with strong direction, should be LTR by default;
+        - the second BDI, having an LTR character first, should be LTR by default;
+        - the thord BDI, having an RTL character first, should be RTL by default.