Merge inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 03 Apr 2014 15:24:54 -0400
changeset 176964 6c924a0185401f12b0627f662964b62e21f706a2
parent 176938 47ce787bc1b38568e0bddb3aaaeccc5dde44bbe3 (current diff)
parent 176963 e6531852947f9a4aca21410f19a1cbacba1d4843 (diff)
child 176969 27d2160ba2d5c553145914f098102862a972fb8d
child 177008 a433a41e7a111be3786b63cbe2bc242602d3a46b
child 177041 6a9a14232208275ff2a9df4b119c06960e53ae0d
push id26538
push userryanvm@gmail.com
push dateThu, 03 Apr 2014 19:23:59 +0000
treeherdermozilla-central@6c924a018540 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone31.0a1
first release with
nightly linux32
6c924a018540 / 31.0a1 / 20140404030202 / files
nightly linux64
6c924a018540 / 31.0a1 / 20140404030202 / files
nightly mac
6c924a018540 / 31.0a1 / 20140404030202 / files
nightly win32
6c924a018540 / 31.0a1 / 20140404030202 / files
nightly win64
6c924a018540 / 31.0a1 / 20140404030202 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c.
nsprpub/aclocal.m4
nsprpub/build/autoconf/acwinpaths.m4
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -898,16 +898,17 @@ pref("apz.max_velocity_inches_per_ms", "
 // memory when zooming in
 pref("apz.x_skate_size_multiplier", "1.25");
 pref("apz.y_skate_size_multiplier", "1.5");
 pref("apz.x_stationary_size_multiplier", "1.5");
 pref("apz.y_stationary_size_multiplier", "1.8");
 pref("apz.enlarge_displayport_when_clipped", true);
 // Use "sticky" axis locking
 pref("apz.axis_lock_mode", 2);
+pref("apz.subframe.enabled", true);
 
 // This preference allows FirefoxOS apps (and content, I think) to force
 // the use of software (instead of hardware accelerated) 2D canvases by
 // creating a context like this:
 //
 //   canvas.getContext('2d', { willReadFrequently: true })
 //
 // Using a software canvas can save memory when JS calls getImageData()
--- a/browser/metro/profile/metro.js
+++ b/browser/metro/profile/metro.js
@@ -53,16 +53,17 @@ pref("apz.pan_repaint_interval", 50);   
 pref("apz.fling_repaint_interval", 50); // prefer 20 fps
 pref("apz.fling_stopped_threshold", "0.2");
 pref("apz.x_skate_size_multiplier", "2.5");
 pref("apz.y_skate_size_multiplier", "2.5");
 pref("apz.min_skate_speed", "10.0");
 // 0 = free, 1 = standard, 2 = sticky
 pref("apz.axis_lock_mode", 2);
 pref("apz.cross_slide.enabled", true);
+pref("apz.subframe.enabled", true);
 
 // Enable Microsoft TSF support by default for imes.
 pref("intl.tsf.enable", true);
 pref("intl.tsf.support_imm", false);
 pref("intl.tsf.hack.atok.create_native_caret", false);
 
 pref("general.autoScroll", true);
 pref("general.smoothScroll", true);
--- a/content/media/TextTrack.cpp
+++ b/content/media/TextTrack.cpp
@@ -104,16 +104,17 @@ TextTrack::GetId(nsAString& aId) const
     mTrackElement->GetAttribute(NS_LITERAL_STRING("id"), aId);
   }
 }
 
 void
 TextTrack::AddCue(TextTrackCue& aCue)
 {
   mCueList->AddCue(aCue);
+  aCue.SetTrack(this);
   if (mTextTrackList) {
     HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
     if (mediaElement) {
       mediaElement->AddCue(aCue);
     }
   }
   SetDirty();
 }
--- a/content/media/TextTrackCue.h
+++ b/content/media/TextTrackCue.h
@@ -11,22 +11,22 @@
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/VTTCueBinding.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIWebVTTParserWrapper.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIDocument.h"
 #include "mozilla/dom/HTMLDivElement.h"
 #include "mozilla/dom/UnionTypes.h"
+#include "mozilla/dom/TextTrack.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTrackElement;
-class TextTrack;
 class TextTrackRegion;
 
 class TextTrackCue MOZ_FINAL : public DOMEventTargetHelper
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextTrackCue, DOMEventTargetHelper)
 
@@ -312,16 +312,21 @@ public:
     return mId.Equals(rhs.mId);
   }
 
   const nsAString& Id() const
   {
     return mId;
   }
 
+  void SetTrack(TextTrack* aTextTrack)
+  {
+    mTrack = aTextTrack;
+  }
+
   /**
    * Produces a tree of anonymous content based on the tree of the processed
    * cue text.
    *
    * Returns a DocumentFragment that is the head of the tree of anonymous
    * content.
    */
   already_AddRefed<DocumentFragment> GetCueAsHTML();
--- a/content/media/test/test_texttrackcue.html
+++ b/content/media/test/test_texttrackcue.html
@@ -48,19 +48,20 @@ SpecialPowers.pushPrefEnv({"set": [["med
 
       // Check if first cue was parsed correctly.
       var cue = cueList[0];
       is(cue.id, "1", "Cue's ID should be 1.");
       is(cue.startTime, 0.5, "Cue's start time should be 0.5.");
       is(cue.endTime, 0.7, "Cue's end time should be 0.7.");
       is(cue.pauseOnExit, false, "Cue's pause on exit flag should be false.");
       is(cue.text, "This", "Cue's text should be set correctly.");
-      // TODO: https://bugzilla.mozilla.org/show_bug.cgi?id=879431
-      // GetTrack() isn't implemented so this *is* returning undefined currently.
-      todo_isnot(cue.track, undefined, "Cue's track should be defined.");
+      is(cue.track, trackElement.track, "Cue's track should be defined.");
+
+      cue.track = null;
+      isnot(cue.track, null, "Cue's track should not be able to be set.");
 
       // Check that all cue times were not rounded
       is(cueList[1].startTime, 1.2, "Second cue's start time should be 1.2.");
       is(cueList[1].endTime, 2.4, "Second cue's end time should be 2.4.");
       is(cueList[2].startTime, 2, "Third cue's start time should be 2.");
       is(cueList[2].endTime, 3.5, "Third cue's end time should be 3.5.");
       is(cueList[3].startTime, 2.71, "Fourth cue's start time should be 2.71.");
       is(cueList[3].endTime, 2.91, "Fourth cue's end time should be 2.91.");
@@ -179,17 +180,19 @@ SpecialPowers.pushPrefEnv({"set": [["med
       is(cue.line, "auto", "Cue's line value should initially be auto.");
       cue.line = 12410
       is(cue.line, 12410, "Cue's line value should now be 12410.");
       cue.line = "auto";
       is(cue.line, "auto", "Cue's line value should now be auto.");
 
       // Check that we can create and add new VTTCues
       var vttCue = new VTTCue(3.999, 4, "foo");
+      is(vttCue.track, undefined, "Cue's track should be undefined.");
       trackElement.track.addCue(vttCue);
+      is(cue.track, trackElement.track, "Cue's track should be defined.");
       is(cueList.length, 7, "Cue list length should now be 7.");
 
       // Check that new VTTCue was added correctly
       cue = cueList[6];
       is(cue.startTime, 3.999, "Cue's start time should be 3.999.");
       is(cue.endTime, 4, "Cue's end time should be 4.");
       is(cue.text, "foo", "Cue's text should be foo.");
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1369,17 +1369,18 @@ class CGConstructNavigatorObject(CGAbstr
   nsRefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv);
   rv.WouldReportJSException();
   if (rv.Failed()) {
     ThrowMethodFailedWithDetails(aCx, rv, "${descriptorName}", "navigatorConstructor");
     return nullptr;
   }
   JS::Rooted<JS::Value> v(aCx);
   if (!WrapNewBindingObject(aCx, aObj, result, &v)) {
-    MOZ_ASSERT(JS_IsExceptionPending(aCx));
+    //XXX Assertion disabled for now, see bug 991271.
+    MOZ_ASSERT(true || JS_IsExceptionPending(aCx));
     return nullptr;
   }
   return &v.toObject();"""
         return string.Template(template).substitute({
             'descriptorName': self.descriptor.name,
         })
 
 
@@ -4724,17 +4725,18 @@ if (!returnArray) {
                 if descriptor.nativeOwnership == 'owned':
                     wrapMethod = "WrapNewBindingNonWrapperCachedOwnedObject"
                 else:
                     wrapMethod = "WrapNewBindingNonWrapperCachedObject"
             wrap = "%s(cx, ${obj}, %s, ${jsvalHandle})" % (wrapMethod, result)
             if not descriptor.hasXPConnectImpls:
                 # Can only fail to wrap as a new-binding object
                 # if they already threw an exception.
-                failed = ("MOZ_ASSERT(JS_IsExceptionPending(cx));\n" +
+                #XXX Assertion disabled for now, see bug 991271.
+                failed = ("MOZ_ASSERT(true || JS_IsExceptionPending(cx));\n" +
                           "%s" % exceptionCode)
             else:
                 if descriptor.notflattened:
                     raise TypeError("%s has XPConnect impls but not flattened; "
                                     "fallback won't work correctly" %
                                     descriptor.interface.identifier.name)
                 # Try old-style wrapping for bindings which might be XPConnect impls.
                 failed = wrapAndSetPtr("HandleNewBindingWrappingFailure(cx, ${obj}, %s, ${jsvalHandle})" % result)
@@ -11262,17 +11264,18 @@ class CGJSImplMethod(CGJSImplMember):
             constructorArgs = [arg.name for arg in args[2:]]
             constructorArgs.append("js::GetObjectCompartment(scopeObj)")
             initCall = """
 // Wrap the object before calling __Init so that __DOM_IMPL__ is available.
 nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(window);
 JS::Rooted<JSObject*> scopeObj(cx, globalHolder->GetGlobalJSObject());
 JS::Rooted<JS::Value> wrappedVal(cx);
 if (!WrapNewBindingObject(cx, scopeObj, impl, &wrappedVal)) {
-  MOZ_ASSERT(JS_IsExceptionPending(cx));
+  //XXX Assertion disabled for now, see bug 991271.
+  MOZ_ASSERT(true || JS_IsExceptionPending(cx));
   aRv.Throw(NS_ERROR_UNEXPECTED);
   return nullptr;
 }
 // Initialize the object with the constructor arguments.
 impl->mImpl->__Init(%s);
 if (aRv.Failed()) {
   return nullptr;
 }""" % (", ".join(constructorArgs))
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -114,16 +114,17 @@ private:
   DECL_GFX_PREF(Once, "apz.fling_friction",                    APZFlingFriction, float, 0.002f);
   DECL_GFX_PREF(Live, "apz.fling_repaint_interval",            APZFlingRepaintInterval, int32_t, 75);
   DECL_GFX_PREF(Once, "apz.fling_stopped_threshold",           APZFlingStoppedThreshold, float, 0.01f);
   DECL_GFX_PREF(Once, "apz.max_velocity_inches_per_ms",        APZMaxVelocity, float, -1.0f);
   DECL_GFX_PREF(Once, "apz.max_velocity_queue_size",           APZMaxVelocityQueueSize, uint32_t, 5);
   DECL_GFX_PREF(Live, "apz.min_skate_speed",                   APZMinSkateSpeed, float, 1.0f);
   DECL_GFX_PREF(Live, "apz.num_paint_duration_samples",        APZNumPaintDurationSamples, int32_t, 3);
   DECL_GFX_PREF(Live, "apz.pan_repaint_interval",              APZPanRepaintInterval, int32_t, 250);
+  DECL_GFX_PREF(Live, "apz.subframe.enabled",                  APZSubframeEnabled, bool, false);
   DECL_GFX_PREF(Live, "apz.touch_start_tolerance",             APZTouchStartTolerance, float, 1.0f/4.5f);
   DECL_GFX_PREF(Live, "apz.use_paint_duration",                APZUsePaintDuration, bool, true);
   DECL_GFX_PREF(Live, "apz.velocity_bias",                     APZVelocityBias, float, 1.0f);
   DECL_GFX_PREF(Live, "apz.x_skate_size_multiplier",           APZXSkateSizeMultiplier, float, 1.5f);
   DECL_GFX_PREF(Live, "apz.x_stationary_size_multiplier",      APZXStationarySizeMultiplier, float, 3.0f);
   DECL_GFX_PREF(Live, "apz.y_skate_size_multiplier",           APZYSkateSizeMultiplier, float, 2.5f);
   DECL_GFX_PREF(Live, "apz.y_stationary_size_multiplier",      APZYStationarySizeMultiplier, float, 3.5f);
 
--- a/image/src/imgLoader.cpp
+++ b/image/src/imgLoader.cpp
@@ -396,17 +396,16 @@ static nsresult NewImageChannel(nsIChann
                                 nsIURI *aReferringURI,
                                 nsILoadGroup *aLoadGroup,
                                 const nsCString& aAcceptHeader,
                                 nsLoadFlags aLoadFlags,
                                 nsIChannelPolicy *aPolicy,
                                 nsIPrincipal *aLoadingPrincipal)
 {
   nsresult rv;
-  nsCOMPtr<nsIChannel> newChannel;
   nsCOMPtr<nsIHttpChannel> newHttpChannel;
 
   nsCOMPtr<nsIInterfaceRequestor> callbacks;
 
   if (aLoadGroup) {
     // Get the notification callbacks from the load group for the new channel.
     //
     // XXX: This is not exactly correct, because the network request could be
@@ -458,16 +457,28 @@ static nsresult NewImageChannel(nsIChann
 
     p->AdjustPriority(priority);
   }
 
   bool setOwner = nsContentUtils::SetUpChannelOwner(aLoadingPrincipal,
                                                       *aResult, aURI, false);
   *aForcePrincipalCheckForCacheEntry = setOwner;
 
+  // Create a new loadgroup for this new channel, using the old group as
+  // the parent. The indirection keeps the channel insulated from cancels,
+  // but does allow a way for this revalidation to be associated with at
+  // least one base load group for scheduling/caching purposes.
+
+  nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
+  nsCOMPtr<nsILoadGroupChild> childLoadGroup = do_QueryInterface(loadGroup);
+  if (childLoadGroup) {
+    childLoadGroup->SetParentLoadGroup(aLoadGroup);
+  }
+  (*aResult)->SetLoadGroup(loadGroup);
+
   return NS_OK;
 }
 
 static uint32_t SecondsFromPRTime(PRTime prTime)
 {
   return uint32_t(int64_t(prTime) / int64_t(PR_USEC_PER_SEC));
 }
 
@@ -1674,28 +1685,19 @@ nsresult imgLoader::LoadImage(nsIURI *aU
 
     MOZ_ASSERT(NS_UsePrivateBrowsing(newChannel) == mRespectPrivacy);
 
     NewRequestAndEntry(forcePrincipalCheck, this, getter_AddRefs(request), getter_AddRefs(entry));
 
     PR_LOG(GetImgLog(), PR_LOG_DEBUG,
            ("[this=%p] imgLoader::LoadImage -- Created new imgRequest [request=%p]\n", this, request.get()));
 
-    // Create a loadgroup for this new channel.  This way if the channel
-    // is redirected, we'll have a way to cancel the resulting channel.
-    // Inform the new loadgroup of the old one so they can still be correlated
-    // together as a logical group.
-    nsCOMPtr<nsILoadGroup> loadGroup =
-        do_CreateInstance(NS_LOADGROUP_CONTRACTID);
-    nsCOMPtr<nsILoadGroupChild> childLoadGroup = do_QueryInterface(loadGroup);
-    if (childLoadGroup)
-      childLoadGroup->SetParentLoadGroup(aLoadGroup);
-    newChannel->SetLoadGroup(loadGroup);
-
-    request->Init(aURI, aURI, loadGroup, newChannel, entry, aCX,
+    nsCOMPtr<nsILoadGroup> channelLoadGroup;
+    newChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
+    request->Init(aURI, aURI, channelLoadGroup, newChannel, entry, aCX,
                   aLoadingPrincipal, corsmode);
 
     // Pass the inner window ID of the loading document, if possible.
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
     if (doc) {
       request->SetInnerWindowID(doc->InnerWindowID());
     }
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1252,18 +1252,21 @@ Parser<ParseHandler>::newFunction(Generi
         pc = pc->parent;
 
     RootedFunction fun(context);
     JSFunction::Flags flags = (kind == Expression)
                               ? JSFunction::INTERPRETED_LAMBDA
                               : (kind == Arrow)
                                 ? JSFunction::INTERPRETED_LAMBDA_ARROW
                                 : JSFunction::INTERPRETED;
+    gc::AllocKind allocKind = (kind == Arrow)
+                              ? JSFunction::ExtendedFinalizeKind
+                              : JSFunction::FinalizeKind;
     fun = NewFunctionWithProto(context, NullPtr(), nullptr, 0, flags, NullPtr(), atom, proto,
-                               JSFunction::FinalizeKind, MaybeSingletonObject);
+                               allocKind, MaybeSingletonObject);
     if (!fun)
         return nullptr;
     if (options().selfHostingMode)
         fun->setIsSelfHostedBuiltin();
     return fun;
 }
 
 static bool
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/arrow-functions/bug889158.js
@@ -0,0 +1,4 @@
+var f = x => arguments.callee;
+
+for (var i=0; i<5; i++)
+    assertEq(f(), f);
--- a/js/src/jit-test/tests/arrow-functions/length.js
+++ b/js/src/jit-test/tests/arrow-functions/length.js
@@ -2,10 +2,10 @@
 
 assertEq((a => a).hasOwnProperty("length"), true);
 
 assertEq((a => a).length, 1);
 assertEq((() => 0).length, 0);
 assertEq(((a) => 0).length, 1);
 assertEq(((a, b) => 0).length, 2);
 
-assertEq(((...arr) => arr).length, 1);
-assertEq(((a=1, b=2) => 0).length, 2);
+assertEq(((...arr) => arr).length, 0);
+assertEq(((a=1, b=2) => 0).length, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/arrow-functions/this-5.js
@@ -0,0 +1,12 @@
+// Arrow functions can have primitive |this| values.
+
+Number.prototype.foo = function() {
+    "use strict";
+    return () => this;
+}
+
+for (var i=0; i<5; i++) {
+    var n = i.foo()();
+    assertEq(typeof n, "number");
+    assertEq(n, i);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/arrow-functions/this-6.js
@@ -0,0 +1,11 @@
+// Eval expressions in arrow functions use the correct |this| value.
+
+function Dog(name) {
+    this.name = name;
+    this.getName = () => eval("this.name");
+    this.getNameHard = () => eval("(() => this.name)()");
+}
+
+var d = new Dog("Max");
+assertEq(d.getName(), d.name);
+assertEq(d.getNameHard(), d.name);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug984830.js
@@ -0,0 +1,15 @@
+function getTestCaseResult(expected, actual) {
+      if (actual != expected)
+              return Math.abs(actual - expected) <= 1E-10;
+}
+function InstanceOf(object, constructor) {
+      while ( object != null )
+              object = object.__proto__;
+}
+function WorkerBee () {}
+function Engineer () {}
+Engineer.prototype = new WorkerBee();
+var pat = new Engineer();
+getTestCaseResult(pat.__proto__.__proto__.__proto__.__proto__ == Object.prototype);
+getTestCaseResult(InstanceOf(pat, Engineer));
+evaluate("getTestCaseResult( Object.prototype.__proto__ );", { compileAndGo: true });
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1098,16 +1098,27 @@ BaselineCompiler::emit_JSOP_NULL()
 {
     frame.push(NullValue());
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_THIS()
 {
+    if (function() && function()->isArrow()) {
+        // Arrow functions store their (lexical) |this| value in an
+        // extended slot.
+        frame.syncStack(0);
+        Register scratch = R0.scratchReg();
+        masm.loadPtr(frame.addressOfCallee(), scratch);
+        masm.loadValue(Address(scratch, FunctionExtended::offsetOfArrowThisSlot()), R0);
+        frame.push(R0);
+        return true;
+    }
+
     // Keep this value in R0
     frame.pushThis();
 
     // In strict mode code or self-hosted functions, |this| is left alone.
     if (script->strict() || (function() && function()->isSelfHostedBuiltin()))
         return true;
 
     Label skipIC;
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -4057,16 +4057,25 @@ CodeGenerator::visitComputeThis(LCompute
     masm.branchTestObject(Assembler::NotEqual, value, ool->entry());
     masm.unboxObject(value, output);
 
     masm.bind(ool->rejoin());
     return true;
 }
 
 bool
+CodeGenerator::visitLoadArrowThis(LLoadArrowThis *lir)
+{
+    Register callee = ToRegister(lir->callee());
+    ValueOperand output = ToOutValue(lir);
+    masm.loadValue(Address(callee, FunctionExtended::offsetOfArrowThisSlot()), output);
+    return true;
+}
+
+bool
 CodeGenerator::visitArrayLength(LArrayLength *lir)
 {
     Address length(ToRegister(lir->elements()), ObjectElements::offsetOfLength());
     masm.load32(length, ToRegister(lir->output()));
     return true;
 }
 
 bool
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -155,16 +155,17 @@ class CodeGenerator : public CodeGenerat
     bool visitCreateThis(LCreateThis *lir);
     bool visitCreateThisWithProto(LCreateThisWithProto *lir);
     bool visitCreateThisWithTemplate(LCreateThisWithTemplate *lir);
     bool visitCreateArgumentsObject(LCreateArgumentsObject *lir);
     bool visitGetArgumentsObjectArg(LGetArgumentsObjectArg *lir);
     bool visitSetArgumentsObjectArg(LSetArgumentsObjectArg *lir);
     bool visitReturnFromCtor(LReturnFromCtor *lir);
     bool visitComputeThis(LComputeThis *lir);
+    bool visitLoadArrowThis(LLoadArrowThis *lir);
     bool visitArrayLength(LArrayLength *lir);
     bool visitSetArrayLength(LSetArrayLength *lir);
     bool visitTypedArrayLength(LTypedArrayLength *lir);
     bool visitTypedArrayElements(LTypedArrayElements *lir);
     bool visitNeuterCheck(LNeuterCheck *lir);
     bool visitTypedObjectElements(LTypedObjectElements *lir);
     bool visitStringLength(LStringLength *lir);
     bool visitInitializedLength(LInitializedLength *lir);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1652,28 +1652,20 @@ IonBuilder::inspectOpcode(JSOp op)
         return jsop_length();
 
       case JSOP_NOT:
         return jsop_not();
 
       case JSOP_THIS:
         return jsop_this();
 
-      case JSOP_CALLEE:
-      {
-        MDefinition *callee;
-        if (inliningDepth_ == 0) {
-            MInstruction *calleeIns = MCallee::New(alloc());
-            current->add(calleeIns);
-            callee = calleeIns;
-        } else {
-            callee = inlineCallInfo_->fun();
-        }
-        current->push(callee);
-        return true;
+      case JSOP_CALLEE: {
+         MDefinition *callee = getCallee();
+         current->push(callee);
+         return true;
       }
 
       case JSOP_GETPROP:
       case JSOP_CALLPROP:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
         return jsop_getprop(name);
       }
@@ -3027,17 +3019,17 @@ IonBuilder::filterTypesAtTest(MTest *tes
 
     test->filtersUndefinedOrNull(trueBranch, &subject, &removeUndefined, &removeNull);
 
     // The test filters no undefined or null.
     if (!subject)
         return true;
 
     // There is no TypeSet that can get filtered.
-    if (!subject->resultTypeSet())
+    if (!subject->resultTypeSet() || subject->resultTypeSet()->unknown())
         return true;
 
     // Only do this optimization if the typeset does contains null or undefined.
     if ((!(removeUndefined && subject->resultTypeSet()->hasType(types::Type::UndefinedType())) &&
          !(removeNull && subject->resultTypeSet()->hasType(types::Type::NullType()))))
     {
         return true;
     }
@@ -9529,16 +9521,24 @@ IonBuilder::jsop_deffun(uint32_t index)
 }
 
 bool
 IonBuilder::jsop_this()
 {
     if (!info().funMaybeLazy())
         return abort("JSOP_THIS outside of a JSFunction.");
 
+    if (info().funMaybeLazy()->isArrow()) {
+        // Arrow functions store their lexical |this| in an extended slot.
+        MLoadArrowThis *thisObj = MLoadArrowThis::New(alloc(), getCallee());
+        current->add(thisObj);
+        current->push(thisObj);
+        return true;
+    }
+
     if (script()->strict() || info().funMaybeLazy()->isSelfHostedBuiltin()) {
         // No need to wrap primitive |this| in strict mode or self-hosted code.
         current->pushSlot(info().thisSlot());
         return true;
     }
 
     if (thisTypes->getKnownTypeTag() == JSVAL_TYPE_OBJECT ||
         (thisTypes->empty() && baselineFrame_ && baselineFrame_->thisType.isSomeObject()))
@@ -10225,8 +10225,20 @@ IonBuilder::constant(const Value &v)
     return c;
 }
 
 MConstant *
 IonBuilder::constantInt(int32_t i)
 {
     return constant(Int32Value(i));
 }
+
+MDefinition *
+IonBuilder::getCallee()
+{
+    if (inliningDepth_ == 0) {
+        MInstruction *callee = MCallee::New(alloc());
+        current->add(callee);
+        return callee;
+    }
+
+    return inlineCallInfo_->fun();
+}
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -529,16 +529,18 @@ class IonBuilder : public MIRGenerator
                                             TypeDescrSet objTypeReprs,
                                             TypeDescrSet elemTypeReprs,
                                             int32_t elemSize);
 
     // Typed array helpers.
     MInstruction *getTypedArrayLength(MDefinition *obj);
     MInstruction *getTypedArrayElements(MDefinition *obj);
 
+    MDefinition *getCallee();
+
     bool jsop_add(MDefinition *left, MDefinition *right);
     bool jsop_bitnot();
     bool jsop_bitop(JSOp op);
     bool jsop_binary(JSOp op);
     bool jsop_binary(JSOp op, MDefinition *left, MDefinition *right);
     bool jsop_pos();
     bool jsop_neg();
     bool jsop_setarg(uint32_t arg);
--- a/js/src/jit/IonMacroAssembler.cpp
+++ b/js/src/jit/IonMacroAssembler.cpp
@@ -1841,34 +1841,33 @@ MacroAssembler::branchIfNotInterpretedCo
     // perform an aligned 32-bit load and adjust the bitmask accordingly.
     JS_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0);
     JS_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
     JS_STATIC_ASSERT(IS_LITTLE_ENDIAN);
 
     // Emit code for the following test:
     //
     // bool isInterpretedConstructor() const {
-    //     return isInterpreted() && !isFunctionPrototype() &&
+    //     return isInterpreted() && !isFunctionPrototype() && !isArrow() &&
     //         (!isSelfHostedBuiltin() || isSelfHostedConstructor());
     // }
 
     // First, ensure it's a scripted function.
     load32(Address(fun, JSFunction::offsetOfNargs()), scratch);
     branchTest32(Assembler::Zero, scratch, Imm32(JSFunction::INTERPRETED << 16), label);
 
-    // Common case: if both IS_FUN_PROTO and SELF_HOSTED are not set,
-    // we're done.
+    // Common case: if IS_FUN_PROTO, ARROW and SELF_HOSTED are not set,
+    // the function is an interpreted constructor and we're done.
     Label done;
-    uint32_t bits = (JSFunction::IS_FUN_PROTO | JSFunction::SELF_HOSTED) << 16;
+    uint32_t bits = (JSFunction::IS_FUN_PROTO | JSFunction::ARROW | JSFunction::SELF_HOSTED) << 16;
     branchTest32(Assembler::Zero, scratch, Imm32(bits), &done);
     {
-        // The callee is either Function.prototype or self-hosted. Fail if
-        // SELF_HOSTED_CTOR is not set. This means the callee must be
-        // Function.prototype or a self-hosted function that's not a
-        // constructor.
+        // The callee is either Function.prototype, an arrow function or
+        // self-hosted. None of these are constructible, except self-hosted
+        // constructors, so branch to |label| if SELF_HOSTED_CTOR is not set.
         branchTest32(Assembler::Zero, scratch, Imm32(JSFunction::SELF_HOSTED_CTOR << 16), label);
 
 #ifdef DEBUG
         // Function.prototype should not have the SELF_HOSTED_CTOR flag.
         branchTest32(Assembler::Zero, scratch, Imm32(JSFunction::IS_FUN_PROTO << 16), &done);
         breakpoint();
 #endif
     }
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -1051,16 +1051,30 @@ class LComputeThis : public LInstruction
         return getDef(0);
     }
 
     MComputeThis *mir() const {
         return mir_->toComputeThis();
     }
 };
 
+class LLoadArrowThis : public LInstructionHelper<BOX_PIECES, 1, 0>
+{
+  public:
+    LLoadArrowThis(const LAllocation &callee) {
+        setOperand(0, callee);
+    }
+
+    LIR_HEADER(LoadArrowThis)
+
+    const LAllocation *callee() {
+        return getOperand(0);
+    }
+};
+
 // 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.
     MIRType type_;
 
   public:
     LIR_HEADER(StackArgT)
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -59,16 +59,17 @@
     _(CreateThis)                   \
     _(CreateThisWithProto)          \
     _(CreateThisWithTemplate)       \
     _(CreateArgumentsObject)        \
     _(GetArgumentsObjectArg)        \
     _(SetArgumentsObjectArg)        \
     _(ReturnFromCtor)               \
     _(ComputeThis)                  \
+    _(LoadArrowThis)                \
     _(BitNotI)                      \
     _(BitNotV)                      \
     _(BitOpI)                       \
     _(BitOpV)                       \
     _(ShiftI)                       \
     _(UrshD)                        \
     _(Return)                       \
     _(Throw)                        \
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -410,16 +410,26 @@ LIRGenerator::visitComputeThis(MComputeT
     // they aren't clobbered.
     if (!useBox(lir, LComputeThis::ValueIndex, ins->input()))
         return false;
 
     return define(lir, ins) && assignSafepoint(lir, ins);
 }
 
 bool
+LIRGenerator::visitLoadArrowThis(MLoadArrowThis *ins)
+{
+    JS_ASSERT(ins->type() == MIRType_Value);
+    JS_ASSERT(ins->callee()->type() == MIRType_Object);
+
+    LLoadArrowThis *lir = new(alloc()) LLoadArrowThis(useRegister(ins->callee()));
+    return defineBox(lir, ins);
+}
+
+bool
 LIRGenerator::lowerCallArguments(MCall *call)
 {
     uint32_t argc = call->numStackArgs();
     if (argc > maxargslots_)
         maxargslots_ = argc;
 
     for (size_t i = 0; i < argc; i++) {
         MDefinition *arg = call->getArg(i);
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -90,16 +90,17 @@ class LIRGenerator : public LIRGenerator
     bool visitCreateThisWithTemplate(MCreateThisWithTemplate *ins);
     bool visitCreateThisWithProto(MCreateThisWithProto *ins);
     bool visitCreateThis(MCreateThis *ins);
     bool visitCreateArgumentsObject(MCreateArgumentsObject *ins);
     bool visitGetArgumentsObjectArg(MGetArgumentsObjectArg *ins);
     bool visitSetArgumentsObjectArg(MSetArgumentsObjectArg *ins);
     bool visitReturnFromCtor(MReturnFromCtor *ins);
     bool visitComputeThis(MComputeThis *ins);
+    bool visitLoadArrowThis(MLoadArrowThis *ins);
     bool visitCall(MCall *call);
     bool visitApplyArgs(MApplyArgs *apply);
     bool visitBail(MBail *bail);
     bool visitAssertFloat32(MAssertFloat32 *ins);
     bool visitGetDynamicName(MGetDynamicName *ins);
     bool visitFilterArgumentsOrEval(MFilterArgumentsOrEval *ins);
     bool visitCallDirectEval(MCallDirectEval *ins);
     bool visitTest(MTest *test);
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -1987,16 +1987,19 @@ class MBail : public MNullaryInstruction
   public:
     INSTRUCTION_HEADER(Bail)
 
     static MBail *
     New(TempAllocator &alloc) {
         return new(alloc) MBail();
     }
 
+    AliasSet getAliasSet() const {
+        return AliasSet::None();
+    }
 };
 
 class MAssertFloat32 : public MUnaryInstruction
 {
   protected:
     bool mustBeFloat32_;
 
     MAssertFloat32(MDefinition *value, bool mustBeFloat32)
@@ -4393,16 +4396,49 @@ class MComputeThis
     bool possiblyCalls() const {
         return true;
     }
 
     // Note: don't override getAliasSet: the thisObject hook can be
     // effectful.
 };
 
+// Load an arrow function's |this| value.
+class MLoadArrowThis
+  : public MUnaryInstruction,
+    public SingleObjectPolicy
+{
+    MLoadArrowThis(MDefinition *callee)
+      : MUnaryInstruction(callee)
+    {
+        setResultType(MIRType_Value);
+        setMovable();
+    }
+
+  public:
+    INSTRUCTION_HEADER(LoadArrowThis)
+
+    static MLoadArrowThis *New(TempAllocator &alloc, MDefinition *callee) {
+        return new(alloc) MLoadArrowThis(callee);
+    }
+    MDefinition *callee() const {
+        return getOperand(0);
+    }
+    TypePolicy *typePolicy() {
+        return this;
+    }
+    bool congruentTo(MDefinition *ins) const {
+        return congruentIfOperandsEqual(ins);
+    }
+    AliasSet getAliasSet() const {
+        // An arrow function's lexical |this| value is immutable.
+        return AliasSet::None();
+    }
+};
+
 class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode<MPhi>
 {
     js::Vector<MUse, 2, IonAllocPolicy> inputs_;
 
     uint32_t slot_;
     bool hasBackedgeType_;
     bool triedToSpecialize_;
     bool isIterator_;
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -33,16 +33,17 @@ namespace jit {
     _(DefFun)                                                               \
     _(CreateThis)                                                           \
     _(CreateThisWithProto)                                                  \
     _(CreateThisWithTemplate)                                               \
     _(CreateArgumentsObject)                                                \
     _(GetArgumentsObjectArg)                                                \
     _(SetArgumentsObjectArg)                                                \
     _(ComputeThis)                                                          \
+    _(LoadArrowThis)                                                        \
     _(Call)                                                                 \
     _(ApplyArgs)                                                            \
     _(Bail)                                                                 \
     _(AssertFloat32)                                                        \
     _(GetDynamicName)                                                       \
     _(FilterArgumentsOrEval)                                                \
     _(CallDirectEval)                                                       \
     _(BitNot)                                                               \
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -131,16 +131,17 @@ class ParallelSafetyVisitor : public MIn
     UNSAFE_OP(DefFun)
     UNSAFE_OP(CreateThis)
     CUSTOM_OP(CreateThisWithTemplate)
     UNSAFE_OP(CreateThisWithProto)
     UNSAFE_OP(CreateArgumentsObject)
     UNSAFE_OP(GetArgumentsObjectArg)
     UNSAFE_OP(SetArgumentsObjectArg)
     UNSAFE_OP(ComputeThis)
+    UNSAFE_OP(LoadArrowThis)
     CUSTOM_OP(Call)
     UNSAFE_OP(ApplyArgs)
     UNSAFE_OP(Bail)
     UNSAFE_OP(AssertFloat32)
     UNSAFE_OP(GetDynamicName)
     UNSAFE_OP(FilterArgumentsOrEval)
     UNSAFE_OP(CallDirectEval)
     SAFE_OP(BitNot)
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -160,17 +160,17 @@ static const uint16_t poisonPillProps[] 
 static bool
 fun_enumerate(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->is<JSFunction>());
 
     RootedId id(cx);
     bool found;
 
-    if (!obj->isBoundFunction()) {
+    if (!obj->isBoundFunction() && !obj->as<JSFunction>().isArrow()) {
         id = NameToId(cx->names().prototype);
         if (!JSObject::hasProperty(cx, obj, id, &found, 0))
             return false;
     }
 
     id = NameToId(cx->names().length);
     if (!JSObject::hasProperty(cx, obj, id, &found, 0))
         return false;
@@ -281,18 +281,20 @@ js::fun_resolve(JSContext *cx, HandleObj
          * created eagerly.
          *
          * ES5 15.3.4: the non-native function object named Function.prototype
          * does not have a .prototype property.
          *
          * ES5 15.3.4.5: bound functions don't have a prototype property. The
          * isBuiltin() test covers this case because bound functions are native
          * (and thus built-in) functions by definition/construction.
+         *
+         * ES6 19.2.4.3: arrow functions also don't have a prototype property.
          */
-        if (fun->isBuiltin() || fun->isFunctionPrototype())
+        if (fun->isBuiltin() || fun->isArrow() || fun->isFunctionPrototype())
             return true;
 
         if (!ResolveInterpretedFunctionPrototype(cx, fun))
             return false;
         objp.set(fun);
         return true;
     }
 
@@ -415,38 +417,40 @@ js::XDRInterpretedFunction(XDRState<mode
         JS_ASSERT_IF(fun->hasSingletonType() &&
                      !((lazy && lazy->hasBeenCloned()) || (script && script->hasBeenCloned())),
                      fun->environment() == nullptr);
     }
 
     if (!xdr->codeUint32(&firstword))
         return false;
 
+    if ((firstword & HasAtom) && !XDRAtom(xdr, &atom))
+        return false;
+    if (!xdr->codeUint32(&flagsword))
+        return false;
+
     if (mode == XDR_DECODE) {
         JSObject *proto = nullptr;
         if (firstword & IsStarGenerator) {
             proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
             if (!proto)
                 return false;
         }
 
+        gc::AllocKind allocKind = uint16_t(flagsword) & JSFunction::EXTENDED
+                                  ? JSFunction::ExtendedFinalizeKind
+                                  : JSFunction::FinalizeKind;
         fun = NewFunctionWithProto(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED,
                                    /* parent = */ NullPtr(), NullPtr(), proto,
-                                   JSFunction::FinalizeKind, TenuredObject);
+                                   allocKind, TenuredObject);
         if (!fun)
             return false;
-        atom = nullptr;
         script = nullptr;
     }
 
-    if ((firstword & HasAtom) && !XDRAtom(xdr, &atom))
-        return false;
-    if (!xdr->codeUint32(&flagsword))
-        return false;
-
     if (firstword & IsLazy) {
         if (!XDRLazyScript(xdr, enclosingScope, enclosingScript, fun, &lazy))
             return false;
     } else {
         if (!XDRScript(xdr, enclosingScope, enclosingScript, fun, &script))
             return false;
     }
 
@@ -482,20 +486,23 @@ js::CloneFunctionAndScript(JSContext *cx
 {
     /* NB: Keep this in sync with XDRInterpretedFunction. */
     JSObject *cloneProto = nullptr;
     if (srcFun->isStarGenerator()) {
         cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
         if (!cloneProto)
             return nullptr;
     }
+
+    gc::AllocKind allocKind = srcFun->isExtended()
+                              ? JSFunction::ExtendedFinalizeKind
+                              : JSFunction::FinalizeKind;
     RootedFunction clone(cx, NewFunctionWithProto(cx, NullPtr(), nullptr, 0,
                                                   JSFunction::INTERPRETED, NullPtr(), NullPtr(),
-                                                  cloneProto, JSFunction::FinalizeKind,
-                                                  TenuredObject));
+                                                  cloneProto, allocKind, TenuredObject));
     if (!clone)
         return nullptr;
 
     RootedScript srcScript(cx, srcFun->getOrCreateScript(cx));
     if (!srcScript)
         return nullptr;
     RootedScript clonedScript(cx, CloneScript(cx, enclosingScope, clone, srcScript));
     if (!clonedScript)
@@ -677,25 +684,16 @@ FindBody(JSContext *cx, HandleFunction f
 }
 
 JSString *
 js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lambdaParen)
 {
     if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
         return nullptr;
 
-    // If the object is an automatically-bound arrow function, get the source
-    // of the pre-binding target.
-    if (fun->isArrow() && fun->isBoundFunction()) {
-        JSObject *target = fun->getBoundFunctionTarget();
-        RootedFunction targetFun(cx, &target->as<JSFunction>());
-        JS_ASSERT(targetFun->isArrow());
-        return FunctionToString(cx, targetFun, bodyOnly, lambdaParen);
-    }
-
     if (IsAsmJSModule(fun))
         return AsmJSModuleToString(cx, fun, !lambdaParen);
     if (IsAsmJSFunction(fun))
         return AsmJSFunctionToString(cx, fun);
 
     StringBuffer out(cx);
     RootedScript script(cx);
 
@@ -1243,27 +1241,16 @@ JSFunction::relazify(JSTracer *trc)
 /* ES5 15.3.4.5.1 and 15.3.4.5.2. */
 bool
 js::CallOrConstructBoundFunction(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedFunction fun(cx, &args.callee().as<JSFunction>());
     JS_ASSERT(fun->isBoundFunction());
 
-    bool constructing = args.isConstructing();
-    if (constructing && fun->isArrow()) {
-        /*
-         * Per spec, arrow functions do not even have a [[Construct]] method.
-         * So before anything else, if we are an arrow function, make sure we
-         * don't even get here. You never saw me. Burn this comment.
-         */
-        RootedValue v(cx, ObjectValue(*fun));
-        return ReportIsNotFunction(cx, v, -1, CONSTRUCT);
-    }
-
     /* 15.3.4.5.1 step 1, 15.3.4.5.2 step 3. */
     unsigned argslen = fun->getBoundFunctionArgumentCount();
 
     if (args.length() + argslen > ARGS_LENGTH_MAX) {
         js_ReportAllocationOverflow(cx);
         return false;
     }
 
@@ -1280,16 +1267,17 @@ js::CallOrConstructBoundFunction(JSConte
     /* 15.3.4.5.1, 15.3.4.5.2 step 4. */
     for (unsigned i = 0; i < argslen; i++)
         invokeArgs[i].set(fun->getBoundFunctionArgument(i));
     PodCopy(invokeArgs.array() + argslen, vp + 2, args.length());
 
     /* 15.3.4.5.1, 15.3.4.5.2 step 5. */
     invokeArgs.setCallee(ObjectValue(*target));
 
+    bool constructing = args.isConstructing();
     if (!constructing)
         invokeArgs.setThis(boundThis);
 
     if (constructing ? !InvokeConstructor(cx, invokeArgs) : !Invoke(cx, invokeArgs))
         return false;
 
     args.rval().set(invokeArgs.rval());
     return true;
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -137,37 +137,27 @@ class JSFunction : public JSObject
 
     bool hasJITCode() const {
         if (!hasScript())
             return false;
 
         return nonLazyScript()->hasBaselineScript() || nonLazyScript()->hasIonScript();
     }
 
-    // Arrow functions are a little weird.
-    //
-    // Like all functions, (1) when the compiler parses an arrow function, it
-    // creates a function object that gets stored with the enclosing script;
-    // and (2) at run time the script's function object is cloned.
-    //
-    // But then, unlike other functions, (3) a bound function is created with
-    // the clone as its target.
-    //
-    // isArrow() is true for all three of these Function objects.
-    // isBoundFunction() is true only for the last one.
+    // Arrow functions store their lexical |this| in the first extended slot.
     bool isArrow()                  const { return flags() & ARROW; }
 
     /* Compound attributes: */
     bool isBuiltin() const {
         return isNative() || isSelfHostedBuiltin();
     }
     bool isInterpretedConstructor() const {
         // Note: the JITs inline this check, so be careful when making changes
         // here. See IonMacroAssembler::branchIfNotInterpretedConstructor.
-        return isInterpreted() && !isFunctionPrototype() &&
+        return isInterpreted() && !isFunctionPrototype() && !isArrow() &&
                (!isSelfHostedBuiltin() || isSelfHostedConstructor());
     }
     bool isNamedLambda() const {
         return isLambda() && displayAtom() && !hasGuessedAtom();
     }
     bool hasParallelNative() const {
         return isNative() && jitInfo() && jitInfo()->hasParallelNative();
     }
@@ -543,16 +533,20 @@ bool IsConstructor(const Value &v);
  * Most functions do not have these extensions, but enough do that efficient
  * storage is required (no malloc'ed reserved slots).
  */
 class FunctionExtended : public JSFunction
 {
   public:
     static const unsigned NUM_EXTENDED_SLOTS = 2;
 
+    static inline size_t offsetOfArrowThisSlot() {
+        return offsetof(FunctionExtended, extendedSlots) + 0 * sizeof(HeapValue);
+    }
+
   private:
     friend class JSFunction;
 
     /* Reserved slots available for storage by particular native functions. */
     HeapValue extendedSlots[NUM_EXTENDED_SLOTS];
 };
 
 extern JSFunction *
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -2725,72 +2725,64 @@ UpdatePropertyType(ExclusiveContext *cx,
          */
         if (indexed || !value.isUndefined() || !CanHaveEmptyPropertyTypesForOwnProperty(obj)) {
             Type type = GetValueType(value);
             types->TypeSet::addType(type, &cx->typeLifoAlloc());
         }
     }
 }
 
-bool
-TypeObject::addProperty(ExclusiveContext *cx, jsid id, Property **pprop)
+void
+TypeObject::updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *types)
 {
-    JS_ASSERT(!*pprop);
-    Property *base = cx->typeLifoAlloc().new_<Property>(id);
-    if (!base)
-        return false;
-
-    if (singleton() && singleton()->isNative()) {
-        /*
-         * Fill the property in with any type the object already has in an own
-         * property. We are only interested in plain native properties and
-         * dense elements which don't go through a barrier when read by the VM
-         * or jitcode.
-         */
-
-        if (JSID_IS_VOID(id)) {
-            /* Go through all shapes on the object to get integer-valued properties. */
-            RootedShape shape(cx, singleton()->lastProperty());
-            while (!shape->isEmptyShape()) {
-                if (JSID_IS_VOID(IdToTypeId(shape->propid())))
-                    UpdatePropertyType(cx, &base->types, singleton(), shape, true);
-                shape = shape->previous();
+    InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s",
+              InferSpewColor(types), types, InferSpewColorReset(),
+              TypeObjectString(this), TypeIdString(id));
+
+    if (!singleton() || !singleton()->isNative())
+        return;
+
+    /*
+     * Fill the property in with any type the object already has in an own
+     * property. We are only interested in plain native properties and
+     * dense elements which don't go through a barrier when read by the VM
+     * or jitcode.
+     */
+
+    if (JSID_IS_VOID(id)) {
+        /* Go through all shapes on the object to get integer-valued properties. */
+        RootedShape shape(cx, singleton()->lastProperty());
+        while (!shape->isEmptyShape()) {
+            if (JSID_IS_VOID(IdToTypeId(shape->propid())))
+                UpdatePropertyType(cx, types, singleton(), shape, true);
+            shape = shape->previous();
+        }
+
+        /* Also get values of any dense elements in the object. */
+        for (size_t i = 0; i < singleton()->getDenseInitializedLength(); i++) {
+            const Value &value = singleton()->getDenseElement(i);
+            if (!value.isMagic(JS_ELEMENTS_HOLE)) {
+                Type type = GetValueType(value);
+                types->TypeSet::addType(type, &cx->typeLifoAlloc());
             }
-
-            /* Also get values of any dense elements in the object. */
-            for (size_t i = 0; i < singleton()->getDenseInitializedLength(); i++) {
-                const Value &value = singleton()->getDenseElement(i);
-                if (!value.isMagic(JS_ELEMENTS_HOLE)) {
-                    Type type = GetValueType(value);
-                    base->types.TypeSet::addType(type, &cx->typeLifoAlloc());
-                }
-            }
-        } else if (!JSID_IS_EMPTY(id)) {
-            RootedId rootedId(cx, id);
-            Shape *shape = singleton()->nativeLookup(cx, rootedId);
-            if (shape)
-                UpdatePropertyType(cx, &base->types, singleton(), shape, false);
         }
-
-        if (singleton()->watched()) {
-            /*
-             * Mark the property as non-data, to inhibit optimizations on it
-             * and avoid bypassing the watchpoint handler.
-             */
-            base->types.setNonDataProperty(cx);
-        }
+    } else if (!JSID_IS_EMPTY(id)) {
+        RootedId rootedId(cx, id);
+        Shape *shape = singleton()->nativeLookup(cx, rootedId);
+        if (shape)
+            UpdatePropertyType(cx, types, singleton(), shape, false);
     }
 
-    *pprop = base;
-
-    InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s",
-              InferSpewColor(&base->types), &base->types, InferSpewColorReset(),
-              TypeObjectString(this), TypeIdString(id));
-
-    return true;
+    if (singleton()->watched()) {
+        /*
+         * Mark the property as non-data, to inhibit optimizations on it
+         * and avoid bypassing the watchpoint handler.
+         */
+        types->setNonDataProperty(cx);
+    }
 }
 
 bool
 TypeObject::addDefiniteProperties(ExclusiveContext *cx, JSObject *obj)
 {
     if (unknownProperties())
         return true;
 
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -1103,17 +1103,17 @@ struct TypeObject : gc::BarrieredCell<Ty
     /* Get a property only if it already exists. */
     inline HeapTypeSet *maybeGetProperty(jsid id);
 
     inline unsigned getPropertyCount();
     inline Property *getProperty(unsigned i);
 
     /* Helpers */
 
-    bool addProperty(ExclusiveContext *cx, jsid id, Property **pprop);
+    void updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *types);
     bool addDefiniteProperties(ExclusiveContext *cx, JSObject *obj);
     bool matchDefiniteProperties(HandleObject obj);
     void addPrototype(JSContext *cx, TypeObject *proto);
     void addPropertyType(ExclusiveContext *cx, jsid id, Type type);
     void addPropertyType(ExclusiveContext *cx, jsid id, const Value &value);
     void markPropertyNonData(ExclusiveContext *cx, jsid id);
     void markPropertyNonWritable(ExclusiveContext *cx, jsid id);
     void markStateChange(ExclusiveContext *cx);
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -1233,49 +1233,45 @@ TypeObject::getProperty(ExclusiveContext
 
     JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
     JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
     JS_ASSERT(!unknownProperties());
 
     if (HeapTypeSet *types = maybeGetProperty(id))
         return types;
 
+    Property *base = cx->typeLifoAlloc().new_<Property>(id);
+    if (!base) {
+        markUnknown(cx);
+        return nullptr;
+    }
+
     uint32_t propertyCount = basePropertyCount();
     Property **pprop = HashSetInsert<jsid,Property,Property>
         (cx->typeLifoAlloc(), propertySet, propertyCount, id);
     if (!pprop) {
         markUnknown(cx);
         return nullptr;
     }
 
     JS_ASSERT(!*pprop);
 
     setBasePropertyCount(propertyCount);
-    if (!addProperty(cx, id, pprop)) {
-        markUnknown(cx);
-        return nullptr;
-    }
+    *pprop = base;
+
+    updateNewPropertyTypes(cx, id, &base->types);
 
     if (propertyCount == OBJECT_FLAG_PROPERTY_COUNT_LIMIT) {
+        // We hit the maximum number of properties the object can have, mark
+        // the object unknown so that new properties will not be added in the
+        // future.
         markUnknown(cx);
-
-        /*
-         * Return an arbitrary property in the object, as all have unknown
-         * type and are treated as non-data properties.
-         */
-        unsigned count = getPropertyCount();
-        for (unsigned i = 0; i < count; i++) {
-            if (Property *prop = getProperty(i))
-                return &prop->types;
-        }
-
-        MOZ_ASSUME_UNREACHABLE("Missing property");
     }
 
-    return &(*pprop)->types;
+    return &base->types;
 }
 
 inline HeapTypeSet *
 TypeObject::maybeGetProperty(jsid id)
 {
     JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
     JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
     JS_ASSERT(!unknownProperties());
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -28,16 +28,17 @@
 #include "vm/GeneratorObject.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/Shape.h"
 #include "vm/StopIterationObject.h"
 
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
+#include "jsscriptinlines.h"
 
 #include "vm/Stack-inl.h"
 #include "vm/String-inl.h"
 
 using namespace js;
 using namespace js::gc;
 using JS::ForOfIterator;
 
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -26,16 +26,26 @@
 #include "vm/String-inl.h"
 
 namespace js {
 
 inline bool
 ComputeThis(JSContext *cx, AbstractFramePtr frame)
 {
     JS_ASSERT_IF(frame.isInterpreterFrame(), !frame.asInterpreterFrame()->runningInJit());
+
+    if (frame.isFunctionFrame() && frame.fun()->isArrow()) {
+        /*
+         * Arrow functions store their (lexical) |this| value in an
+         * extended slot.
+         */
+        frame.thisValue() = frame.fun()->getExtendedSlot(0);
+        return true;
+    }
+
     if (frame.thisValue().isObject())
         return true;
     RootedValue thisv(cx, frame.thisValue());
     if (frame.isFunctionFrame()) {
         if (frame.fun()->strict() || frame.fun()->isSelfHostedBuiltin())
             return true;
         /*
          * Eval function frames have their own |this| slot, which is a copy of the function's
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -3622,20 +3622,18 @@ JSObject *
 js::LambdaArrow(JSContext *cx, HandleFunction fun, HandleObject parent, HandleValue thisv)
 {
     MOZ_ASSERT(fun->isArrow());
 
     RootedObject clone(cx, CloneFunctionObjectIfNotSingleton(cx, fun, parent, TenuredObject));
     if (!clone)
         return nullptr;
 
-    clone = js_fun_bind(cx, clone, thisv, nullptr, 0);
-    if (!clone)
-        return nullptr;
-    clone->as<JSFunction>().setArrow();
+    MOZ_ASSERT(clone->as<JSFunction>().isArrow());
+    clone->as<JSFunction>().setExtendedSlot(0, thisv);
 
     MOZ_ASSERT(clone->global() == clone->global());
     return clone;
 }
 
 bool
 js::DefFunOperation(JSContext *cx, HandleScript script, HandleObject scopeChain,
                     HandleFunction funArg)
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -18,17 +18,17 @@ namespace js {
  * Bytecode version number. Increment the subtrahend whenever JS bytecode
  * changes incompatibly.
  *
  * This version number is XDR'd near the front of xdr bytecode and
  * aborts deserialization if there is a mismatch between the current
  * and saved versions. If deserialization fails, the data should be
  * invalidated if possible.
  */
-static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 170);
+static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 171);
 
 class XDRBuffer {
   public:
     XDRBuffer(JSContext *cx)
       : context(cx), base(nullptr), cursor(nullptr), limit(nullptr) { }
 
     JSContext *cx() const {
         return context;
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -47,16 +47,17 @@
 #include "mozilla/Attributes.h"
 #include "ScrollbarActivity.h"
 #include "nsRefreshDriver.h"
 #include "nsThemeConstants.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsIScrollPositionListener.h"
 #include "StickyScrollContainer.h"
 #include "nsIFrameInlines.h"
+#include "gfxPrefs.h"
 #include <algorithm>
 #include <cstdlib> // for std::abs(int/long)
 #include <cmath> // for std::abs(float/double)
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layout;
 
@@ -2580,20 +2581,20 @@ ScrollFrameHelper::BuildDisplayList(nsDi
     bool isHScrollable = (scrollRange.width > 0)
                       && (styles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN);
     // The check for scroll bars was added in bug 825692 to prevent layerization
     // of text inputs for performance reasons. However, if a text input is
     // focused we want to layerize it so we can async scroll it (bug 946408).
     bool wantLayerV = isVScrollable && (mVScrollbarBox || isFocused);
     bool wantLayerH = isHScrollable && (mHScrollbarBox || isFocused);
     // TODO Turn this on for inprocess OMTC on all platforms
-    bool wantSubAPZC = (XRE_GetProcessType() == GeckoProcessType_Content);
-#ifdef XP_WIN
-    if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
-      wantSubAPZC = true;
+    bool wantSubAPZC = gfxPrefs::APZSubframeEnabled();
+#ifdef MOZ_WIDGET_GONK
+    if (XRE_GetProcessType() != GeckoProcessType_Content) {
+      wantSubAPZC = false;
     }
 #endif
     shouldBuildLayer =
       wantSubAPZC &&
       (wantLayerV || wantLayerH) &&
       // If we are the root scroll frame for the display root then we don't need a scroll
       // info layer to make a RecordFrameMetrics call for us as
       // nsDisplayList::PaintForFrame already calls RecordFrameMetrics for us.
--- a/layout/style/test/animation_utils.js
+++ b/layout/style/test/animation_utils.js
@@ -55,8 +55,128 @@ var gTF = {
   "step_start": step_start(1),
   "step_end": step_end(1),
 };
 
 function is_approx(float1, float2, error, desc) {
   ok(Math.abs(float1 - float2) < error,
      desc + ": " + float1 + " and " + float2 + " should be within " + error);
 }
+
+// Checks if off-main thread animation (OMTA) is available, and if it is, runs
+// the provided callback function. If OMTA is not available or is not
+// functioning correctly, the second callback, aOnSkip, is run instead.
+//
+// This function also does an internal test to verify that OMTA is working at
+// all so that if OMTA is not functioning correctly when it is expected to
+// function only a single failure is produced.
+//
+// Since this function relies on various asynchronous operations, the caller is
+// responsible for calling SimpleTest.waitForExplicitFinish() before calling
+// this and SimpleTest.finish() within aTestFunction and aOnSkip.
+function runOMTATest(aTestFunction, aOnSkip) {
+  const OMTAPrefKey = "layers.offmainthreadcomposition.async-animations";
+  var utils      = SpecialPowers.DOMWindowUtils;
+  var expectOMTA = utils.layerManagerRemote &&
+                   // ^ Off-main thread animation cannot be used if off-main
+                   // thread composition (OMTC) is not available
+                   SpecialPowers.getBoolPref(OMTAPrefKey);
+
+  isOMTAWorking().then(function(isWorking) {
+    if (expectOMTA) {
+      if (isWorking) {
+        aTestFunction();
+      } else {
+        // We only call this when we know it will fail as otherwise in the
+        // regular success case we will end up inflating the "passed tests"
+        // count by 1
+        ok(isWorking, "OMTA is working as expected");
+        aOnSkip();
+      }
+    } else {
+      todo(isWorking, "OMTA is working");
+      aOnSkip();
+    }
+  }).catch(function(err) {
+    ok(false, err);
+    aOnSkip();
+  });
+
+  function isOMTAWorking() {
+    // Create keyframes rule
+    const animationName = "a6ce3091ed85"; // Random name to avoid clashes
+    var ruleText = "@keyframes " + animationName +
+                   " { from { opacity: 0.5 } to { opacity 0.5 } }";
+    var style = document.createElement("style");
+    style.appendChild(document.createTextNode(ruleText));
+    document.head.appendChild(style);
+
+    // Create animation target
+    var div = document.createElement("div");
+    document.body.appendChild(div);
+
+    // Give the target geometry so it is eligible for layerization
+    div.style.width  = "100px";
+    div.style.height = "100px";
+    div.style.backgroundColor = "white";
+
+    // Common clean up code
+    var cleanUp = function() {
+      div.parentNode.removeChild(div);
+      style.parentNode.removeChild(style);
+      if (utils.isTestControllingRefreshes) {
+        utils.restoreNormalRefresh();
+      }
+    };
+
+    return waitForDocumentLoad()
+      .then(loadPaintListener)
+      .then(function() {
+        // Put refresh driver under test control and trigger animation
+        utils.advanceTimeAndRefresh(0);
+        div.style.animation = animationName + " 10s";
+
+        // Trigger style flush
+        div.clientTop;
+        return waitForPaints();
+      }).then(function() {
+        var opacity = utils.getOMTAStyle(div, "opacity");
+        cleanUp();
+        return Promise.resolve(opacity == 0.5);
+      }).catch(function(err) {
+        cleanUp();
+        return Promise.reject(err);
+      });
+  }
+
+  function waitForDocumentLoad() {
+    return new Promise(function(resolve, reject) {
+      if (document.readyState === "complete") {
+        resolve();
+      } else {
+        window.addEventListener("load", resolve);
+      }
+    });
+  }
+
+  function waitForPaints() {
+    return new Promise(function(resolve, reject) {
+      waitForAllPaintsFlushed(resolve);
+    });
+  }
+
+  function loadPaintListener() {
+    return new Promise(function(resolve, reject) {
+      if (typeof(window.waitForAllPaints) !== "function") {
+        var script = document.createElement("script");
+        script.onload = resolve;
+        script.onerror = function() {
+          reject(new Error("Failed to load paint listener"));
+        };
+        script.src = "/tests/SimpleTest/paint_listener.js";
+        var firstScript = document.scripts[0];
+        firstScript.parentNode.insertBefore(script, firstScript);
+      } else {
+        resolve();
+      }
+    });
+  }
+}
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -29,16 +29,17 @@ support-files =
   visited-pref-iframe.html
   xbl_bindings.xml
 generated-files = css_properties.js
 
 [test_acid3_test46.html]
 [test_all_shorthand.html]
 [test_animations.html]
 skip-if = toolkit == 'android'
+[test_animations_omta.html]
 [test_animations_omta_start.html]
 [test_any_dynamic.html]
 [test_at_rule_parse_serialize.html]
 [test_bug73586.html]
 [test_bug74880.html]
 [test_bug98997.html]
 [test_bug160403.html]
 [test_bug200089.html]
--- a/layout/style/test/test_animations.html
+++ b/layout/style/test/test_animations.html
@@ -1,13 +1,24 @@
 <!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=435442
 -->
+<!--
+
+ ====== PLEASE KEEP THIS IN SYNC WITH test_animations_omta.html =======
+
+ test_animations_omta.html mimicks the content of this file but with
+ extra machinery for testing animation values on the compositor thread.
+
+ If you are making changes to this file or to test_animations_omta.html, please
+ try to keep them consistent where appropriate.
+
+-->
 <head>
   <title>Test for css3-animations (Bug 435442)</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="animation_utils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <style type="text/css">
   @keyframes anim1 {
      0% { margin-left: 0px }
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_animations_omta.html
@@ -0,0 +1,954 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=964646
+-->
+<!--
+
+ ========= PLEASE KEEP THIS IN SYNC WITH test_animations.html =========
+
+ This test mimicks the content of test_animations.html but performs tests
+ specific to animations that run on the compositor thread since they require
+ special (asynchronous) handling. Furthermore, these tests check that
+ animations that are expected to run on the compositor thread, are actually
+ doing so.
+
+ If you are making changes to this file or to test_animations.html, please
+ try to keep them consistent where appropriate.
+
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for css3-animations running on the compositor thread (Bug
+         964646)</title>
+  <script type="application/javascript"
+    src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+    src="/tests/SimpleTest/paint_listener.js"></script>
+  <script type="application/javascript" src="animation_utils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style type="text/css">
+    @keyframes transform-anim {
+      to {
+        transform: translate(100px);
+      }
+    }
+    @keyframes anim1 {
+       0% { transform: translate(0px) }
+       50% { transform: translate(80px) }
+       100% { transform: translate(100px) }
+    }
+    @keyframes anim2 {
+      from { opacity: 0 } to { opacity: 1 }
+    }
+    @keyframes anim3 {
+      from { opacity: 0 } to { opacity: 1 }
+    }
+
+    @keyframes kf1 {
+      50% { transform: translate(50px) }
+      to { transform: translate(150px) }
+    }
+    @keyframes kf2 {
+      from { transform: translate(150px) }
+      50% { transform: translate(50px) }
+    }
+    @keyframes kf3 {
+      25% { transform: translate(100px) }
+    }
+    @keyframes kf4 {
+      to, from { display: inline; transform: translate(37px) }
+    }
+    @keyframes kf_cascade1 {
+      from { transform: translate(50px) }
+      50%, from { transform: translate(30px) }      /* wins: 0% */
+      75%, 85%, 50% { transform: translate(20px) }  /* wins: 75%, 50% */
+      100%, 85% { transform: translate(70px) }      /* wins: 100% */
+      85.1% { transform: translate(60px) }          /* wins: 85.1% */
+      85% { transform: translate(30px) }            /* wins: 85% */
+    }
+    @keyframes kf_cascade2 { from, to { opacity: 0.3 } }
+    @keyframes kf_cascade2 { from, to { transform: translate(50px) } }
+    @keyframes kf_cascade2 { from, to { transform: translate(100px) } }
+
+    .target {
+      /* The animation target needs geometry in order to qualify for OMTA */
+      width: 100px;
+      height: 100px;
+      background-color: white;
+    }
+  </style>
+</head>
+<body>
+<a target="_blank"
+  href="https://bugzilla.mozilla.org/show_bug.cgi?id=964646">Mozilla Bug
+  964646</a>
+<div id="display"></div>
+<pre id="test">
+<script type="application/javascript">
+"use strict";
+
+/** Test for css3-animations running on the compositor thread (Bug 964646) **/
+ 
+// Global state
+var gAsyncTests     = [],
+    gDisplay        = document.getElementById("display"),
+    gDiv            = null,
+    gEventsReceived = [];
+
+SimpleTest.waitForExplicitFinish();
+runOMTATest(function() {
+  // The async test runner returns a Promise that is resolved when the
+  // test is finished so we can chain them together
+  gAsyncTests.reduce(function(sequence, test) {
+    return sequence.then(function() { return runAsyncTest(test); });
+  }, Promise.resolve() /* the start of the sequence */)
+  // Final step in the sequence
+  .then(function() {
+    SimpleTest.finish();
+  });
+}, SimpleTest.finish);
+
+// Takes a generator function that represents a test case. Each point in the
+// test case that waits asynchronously for some result yields a Promise that is
+// resolved when the asychronous action has completed. By chaining these
+// intermediate results together we run the test to completion.
+//
+// This method itself returns a Promise that is resolved when the generator
+// function has completed.
+//
+// This arrangement is based on add_task() which is currently only available
+// in mochitest-chrome (bug 872229). Once add_task is available in
+// mochitest-plain we can remove this function and use add_task instead.
+function runAsyncTest(test) {
+  var generator;
+
+  function step(arg) {
+    var next;
+    try {
+      next = generator.next(arg);
+    } catch (e) {
+      return Promise.reject(e);
+    }
+    if (next.done) {
+      return Promise.resolve(next.value);
+    } else {
+      return Promise.resolve(next.value)
+             .then(step, function(err) { throw err; });
+    }
+  }
+
+  // Put refresh driver under test control
+  advance_clock(0);
+
+  // Run test
+  generator = test();
+  return step()
+  .catch(function(err) {
+    ok(false, err.message);
+    // Clear up the test div in case we aborted the test before doing clean-up
+    if (gDiv) {
+      done_div();
+    }
+  }).then(function() {
+    // Restore clock
+    SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
+  });
+}
+
+function addAsyncTest(generator) {
+  gAsyncTests.push(generator);
+}
+
+//----------------------------------------------------------------------
+//
+// Test cases
+//
+//----------------------------------------------------------------------
+
+// This test is not in test_animations.html but is here to test that
+// transform animations are actually run on the compositor thread as expected.
+addAsyncTest(function *() {
+  new_div("animation: transform-anim linear 300s");
+
+  yield waitForPaints();
+
+  advance_clock(200000);
+  omta_is("transform", { tx: 100 * 2 / 3 }, RunningOn.Compositor,
+          "OMTA animation is animating as expected");
+  done_div();
+});
+
+function *testFillMode(fillMode, fillsBackwards, fillsForwards)
+{
+  var style = "transform: translate(30px); animation: 10s 3s anim1 linear";
+  var desc;
+  if (fillMode.length > 0) {
+    style += " " + fillMode;
+    desc = "fill mode " + fillMode + ": ";
+  } else {
+    desc = "default fill mode: ";
+  }
+  new_div(style);
+  listen();
+
+  // Currently backwards fill is not performed on the compositor thread but we
+  // should wait for paints so we can test that transform values are *not* being
+  // set on the compositor thread.
+  yield waitForPaints();
+
+  if (fillsBackwards)
+    omta_is("transform", { tx: 0 }, RunningOn.MainThread,
+            desc + "does affect value during delay (0s)");
+  else
+    omta_is("transform", { tx: 30 }, RunningOn.MainThread,
+            desc + "doesn't affect value during delay (0s)");
+
+  advance_clock(2000);
+  if (fillsBackwards)
+    omta_is("transform", { tx: 0 }, RunningOn.MainThead,
+            desc + "does affect value during delay (0s)");
+  else
+    omta_is("transform", { tx: 30 }, RunningOn.MainThread,
+            desc + "does affect value during delay (0s)");
+
+  check_events([], "before start in testFillMode");
+  advance_clock(1000);
+  check_events([{ type: "animationstart", target: gDiv,
+                  bubbles: true, cancelable: false,
+                  animationName: "anim1", elapsedTime: 0.0,
+                  pseudoElement: "" }],
+               "right after start in testFillMode");
+
+  // If we have a backwards fill then at the start of the animation we will end
+  // up applying the same value as the fill value. Various optimizations in
+  // RestyleManager may filter out this meaning that the animation doesn't get
+  // added to the compositor thread until the first time the value changes.
+  //
+  // As a result we look for this first sample on either the compositor or the
+  // computed style
+  yield waitForPaints();
+  omta_is("transform", { tx: 0 }, RunningOn.Either,
+          desc + "affects value at start of animation");
+  advance_clock(125);
+  // We might not add the animation to compositor until the second sample (due
+  // to the optimizations mentioned above) so we should wait for paints before
+  // proceeding
+  yield waitForPaints();
+  omta_is("transform", { tx: 2 }, RunningOn.Compositor,
+          desc + "affects value during animation");
+  advance_clock(2375);
+  omta_is("transform", { tx: 40 }, RunningOn.Compositor,
+          desc + "affects value during animation");
+  advance_clock(2500);
+  omta_is("transform", { tx: 80 }, RunningOn.Compositor,
+          desc + "affects value during animation");
+  advance_clock(2500);
+  omta_is("transform", { tx: 90 }, RunningOn.Compositor,
+          desc + "affects value during animation");
+  advance_clock(2375);
+  omta_is("transform", { tx: 99.5 }, RunningOn.Compositor,
+          desc + "affects value during animation");
+  check_events([], "before end in testFillMode");
+  advance_clock(125);
+  check_events([{ type: "animationend", target: gDiv,
+                  bubbles: true, cancelable: false,
+                  animationName: "anim1", elapsedTime: 10.0,
+                  pseudoElement: "" }],
+               "right after end in testFillMode");
+  
+  // Currently the compositor will apply a forwards fill until it gets told by
+  // the main thread to clear the animation. As a result we should wait for
+  // paints to be flushed before checking that the animated value does *not*
+  // appear on the compositor thread.
+  yield waitForPaints();
+  if (fillsForwards)
+    omta_is("transform", { tx: 100 }, RunningOn.MainThread,
+            desc + "affects value at end of animation");
+  advance_clock(10);
+  if (fillsForwards)
+    omta_is("transform", { tx: 100 }, RunningOn.MainThread,
+            desc + "affects value after animation");
+  else
+    omta_is("transform", { tx: 30 }, RunningOn.MainThread,
+            desc + "does not affect value after animation");
+
+  done_div();
+}
+
+addAsyncTest(function() { return testFillMode("", false, false); });
+addAsyncTest(function() { return testFillMode("none", false, false); });
+addAsyncTest(function() { return testFillMode("forwards", false, true); });
+addAsyncTest(function() { return testFillMode("backwards", true, false); });
+addAsyncTest(function() { return testFillMode("both", true, true); });
+
+// Test that animations continue running when the animation name
+// list is changed.
+//
+// test_animations.html combines all these tests into one block but this is
+// difficult for OMTA because currently there are only two properties to which
+// we apply OMTA. Instead we break the test down into a few independent pieces
+// in order to exercise the same functionality.
+
+// Append to list
+addAsyncTest(function *() {
+  new_div("animation: anim1 linear 10s");
+  yield waitForPaints();
+    omta_is("transform", { tx: 0 }, RunningOn.Either,
+            "just anim1, translate at start");
+  advance_clock(1000);
+    omta_is("transform", { tx: 16 }, RunningOn.Compositor,
+            "just anim1, translate at 1s");
+  // append anim2
+  gDiv.style.animation = "anim1 linear 10s, anim2 linear 10s";
+  yield waitForPaintsFlushed();
+    omta_is("transform", { tx: 16 }, RunningOn.Compositor,
+            "anim1 + anim2, translate at 1s");
+    omta_is("opacity", 0, RunningOn.Compositor,
+            "anim1 + anim2, opacity at 1s");
+  advance_clock(1000);
+    omta_is("transform", { tx: 32 }, RunningOn.Compositor,
+            "anim1 + anim2, translate at 2s");
+    omta_is("opacity", 0.1, RunningOn.Compositor,
+            "anim1 + anim2, opacity at 2s");
+  done_div();
+});
+
+// Prepend to list; delete from list
+addAsyncTest(function *() {
+  new_div("animation: anim1 linear 10s");
+  yield waitForPaints();
+    omta_is("transform", { tx: 0 }, RunningOn.Either,
+            "just anim1, translate at start");
+  advance_clock(1000);
+    omta_is("transform", { tx: 16 }, RunningOn.Compositor,
+                     "just anim1, translate at 1s");
+  // prepend anim2
+  gDiv.style.animation = "anim2 linear 10s, anim1 linear 10s";
+  yield waitForPaintsFlushed();
+    omta_is("transform", { tx: 16 }, RunningOn.Compositor,
+            "anim2 + anim1, translate at 1s");
+    omta_is("opacity", 0, RunningOn.Compositor,
+            "anim2 + anim1, opacity at 1s");
+  advance_clock(1000);
+    omta_is("transform", { tx: 32 }, RunningOn.Compositor,
+            "anim2 + anim1, translate at 2s");
+    omta_is("opacity", 0.1, RunningOn.Compositor,
+            "anim2 + anim1, opacity at 2s");
+  // remove anim2 from list
+  gDiv.style.animation = "anim1 linear 10s";
+  yield waitForPaintsFlushed();
+    omta_is("transform", { tx: 32 }, RunningOn.Compositor,
+            "just anim1, translate at 2s");
+    omta_is("opacity", 1, RunningOn.MainThread, "just anim1, opacity at 2s");
+  advance_clock(1000);
+    omta_is("transform", { tx: 48 }, RunningOn.Compositor,
+            "just anim1, translate at 3s");
+    omta_is("opacity", 1, RunningOn.MainThread, "just anim1, opacity at 3s");
+  done_div();
+});
+
+// Swap elements
+addAsyncTest(function *() {
+  new_div("animation: anim1 linear 10s, anim2 linear 10s");
+  yield waitForPaints();
+    omta_is("transform", { tx: 0 }, RunningOn.Either,
+            "anim1 + anim2, translate at start");
+    omta_is("opacity", 0, RunningOn.Compositor,
+            "anim1 + anim2, opacity at start");
+  advance_clock(1000);
+    omta_is("transform", { tx: 16 }, RunningOn.Compositor,
+            "anim1 + anim2, translate at 1s");
+    omta_is("opacity", 0.1, RunningOn.Compositor,
+            "anim1 + anim2, opacity at 1s");
+  // swap anim1 and anim2, change duration of anim2
+  gDiv.style.animation = "anim2 linear 5s, anim1 linear 10s";
+  yield waitForPaintsFlushed();
+    omta_is("transform", { tx: 16 }, RunningOn.Compositor,
+            "anim2 + anim1, translate at 1s");
+    omta_is("opacity", 0.2, RunningOn.Compositor,
+            "anim2 + anim1, opacity at 1s");
+  advance_clock(1000);
+    omta_is("transform", { tx: 32 }, RunningOn.Compositor,
+            "anim2 + anim1, translate at 2s");
+    omta_is("opacity", 0.4, RunningOn.Compositor,
+            "anim2 + anim1, opacity at 2s");
+  // list anim2 twice, last duration wins, original start time still applies
+  gDiv.style.animation = "anim2 linear 5s, anim1 linear 10s, anim2 linear 20s";
+  yield waitForPaintsFlushed();
+    omta_is("transform", { tx: 32 }, RunningOn.Compositor,
+            "anim2 + anim1 + anim2, translate at 2s");
+    // Bug 980769
+    todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.1",
+            "anim2 + anim1 + anim2, opacity at 2s");
+  // drop one of the anim2, and list anim3 as well, which animates
+  // the same property as anim2
+  gDiv.style.animation = "anim1 linear 10s, anim2 linear 20s, anim3 linear 10s";
+  yield waitForPaintsFlushed();
+    omta_is("transform", { tx: 32 }, RunningOn.Compositor,
+            "anim1 + anim2 + anim3, translate at 2s");
+    // Bug 980769
+    todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0",
+            "anim1 + anim2 + anim3, opacity at 2s");
+  advance_clock(1000);
+    omta_is("transform", { tx: 48 }, RunningOn.Compositor,
+            "anim1 + anim2 + anim3, translate at 3s");
+    // Bug 980769
+    todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.1",
+            "anim1 + anim2 + anim3, opacity at 3s");
+  // now swap the anim3 and anim2 order
+  gDiv.style.animation = "anim1 linear 10s, anim3 linear 10s, anim2 linear 20s";
+  yield waitForPaintsFlushed();
+    omta_is("transform", { tx: 48 }, RunningOn.Compositor,
+            "anim1 + anim3 + anim2, translate at 3s");
+    // Bug 980769
+    todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.15",
+            "anim1 + anim3 + anim2, opacity at 3s");
+  advance_clock(2000); // (unlike test_animations.html, we seek 2s forwards here
+                       // since at 4s anim2 and anim3 produce the same result so
+                       // we can't tell which won.)
+    omta_is("transform", { tx: 80 }, RunningOn.Compositor,
+            "anim1 + anim3 + anim2, translate at 5s");
+    // Bug 980769
+    todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.25",
+            "anim1 + anim3 + anim2, opacity at 5s");
+  // swap anim3 and anim2 back
+  gDiv.style.animation = "anim1 linear 10s, anim2 linear 20s, anim3 linear 10s";
+  yield waitForPaintsFlushed();
+    omta_is("transform", { tx: 80 }, RunningOn.Compositor,
+            "anim1 + anim2 + anim3, translate at 5s");
+    // Bug 980769
+    todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.3",
+            "anim1 + anim2 + anim3, opacity at 5s");
+  // seek past end of anim1
+  advance_clock(5100);
+  yield waitForPaints();
+    omta_is("transform", { tx: 0 }, RunningOn.MainThread,
+            "anim1 + anim2 + anim3, translate at 10.1s");
+  // Change the animation fill mode on the completed animation.
+  gDiv.style.animation =
+    "anim1 linear 10s forwards, anim2 linear 20s, anim3 linear 10s";
+  yield waitForPaintsFlushed();
+    omta_is("transform", { tx: 100 }, RunningOn.MainThread,
+            "anim1 + anim2 + anim3, translate at 10.1s with fill mode");
+  advance_clock(900);
+    omta_is("transform", { tx: 100 }, RunningOn.MainThread,
+            "anim1 + anim2 + anim3, translate at 11s with fill mode");
+  // Change the animation duration on the completed animation, so it is
+  // no longer completed.
+  // XXX Not sure about this---there seems to be a bug in test_animations.html
+  // in that it drops the fill mode but the test comment says it has a fill mode
+  gDiv.style.animation = "anim1 linear 20s, anim2 linear 20s, anim3 linear 10s";
+  yield waitForPaintsFlushed();
+    omta_is("transform", { tx: 82 }, RunningOn.Compositor,
+            "anim1 + anim2 + anim3, translate at 11s with fill mode");
+    // Bug 980769 - We should get 0.9 but instead 
+    todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.9",
+            "anim1 + anim2 + anim3, opacity at 11s");
+  done_div();
+});
+
+/*
+ * css3-animations:  3. Keyframes
+ * http://dev.w3.org/csswg/css3-animations/#keyframes
+ */
+
+// Test the rules on keyframes that lack a 0% or 100% rule:
+// (simultaneously, test that reverse animations have their keyframes
+// run backwards)
+
+addAsyncTest(function *() {
+  // 100px at 0%, 50px at 50%, 150px at 100%
+  new_div("transform: translate(100px); " +
+          "animation: kf1 ease 1s alternate infinite");
+  advance_clock(0);
+  yield waitForPaints();
+  omta_is("transform", { tx: 100 }, RunningOn.Compositor, "no-0% at 0.0s");
+  advance_clock(100);
+  omta_is_approx("transform", { tx: 100 - 50 * gTF.ease(0.2) },
+                 RunningOn.Compositor, 0.01, "no-0% at 0.1s");
+  advance_clock(200);
+  omta_is_approx("transform", { tx: 100 - 50 * gTF.ease(0.6) },
+                 RunningOn.Compositor, 0.01, "no-0% at 0.3s");
+  advance_clock(200);
+  omta_is("transform", { tx: 50 }, RunningOn.Compositor, "no-0% at 0.5s");
+  advance_clock(200);
+  omta_is_approx("transform", { tx: 50 + 100 * gTF.ease(0.4) },
+                 RunningOn.Compositor, 0.01, "no-0% at 0.7s");
+  advance_clock(200);
+  omta_is_approx("transform", { tx: 50 + 100 * gTF.ease(0.8) },
+                 RunningOn.Compositor, 0.01, "no-0% at 0.9s");
+  advance_clock(100);
+  omta_is("transform", { tx: 150 }, RunningOn.Compositor, "no-0% at 1.0s");
+  advance_clock(100);
+  omta_is_approx("transform", { tx: 50 + 100 * gTF.ease(0.8) },
+                 RunningOn.Compositor, 0.01, "no-0% at 1.1s");
+  advance_clock(300);
+  omta_is_approx("transform", { tx: 50 + 100 * gTF.ease(0.2) },
+                 RunningOn.Compositor, 0.01, "no-0% at 1.4s");
+  advance_clock(300);
+  omta_is_approx("transform", { tx: 100 - 50 * gTF.ease(0.6) },
+                 RunningOn.Compositor, 0.01, "no-0% at 1.7s");
+  advance_clock(200);
+  omta_is_approx("transform", { tx: 100 - 50 * gTF.ease(0.2) },
+                 RunningOn.Compositor, 0.01, "no-0% at 1.9s");
+  advance_clock(100);
+  omta_is("transform", { tx: 100 }, RunningOn.Compositor, "no-0% at 2.0s");
+  done_div();
+
+  // 150px at 0%, 50px at 50%, 100px at 100%
+  new_div("transform: translate(100px); " +
+          "animation: kf2 ease-in 1s alternate infinite");
+  yield waitForPaints();
+  omta_is("transform", { tx: 150 }, RunningOn.Compositor, "no-100% at 0.0s");
+  advance_clock(100);
+  omta_is_approx("transform", { tx: 150 - 100 * gTF.ease_in(0.2) },
+                 RunningOn.Compositor, 0.01, "no-100% at 0.1s");
+  advance_clock(200);
+  omta_is_approx("transform", { tx: 150 - 100 * gTF.ease_in(0.6) },
+                 RunningOn.Compositor, 0.01, "no-100% at 0.3s");
+  advance_clock(200);
+  omta_is("transform", { tx: 50 }, RunningOn.Compositor, "no-100% at 0.5s");
+  advance_clock(200);
+  omta_is_approx("transform", { tx: 50 + 50 * gTF.ease_in(0.4) },
+                 RunningOn.Compositor, 0.01, "no-100% at 0.7s");
+  advance_clock(200);
+  omta_is_approx("transform", { tx: 50 + 50 * gTF.ease_in(0.8) },
+                 RunningOn.Compositor, 0.01, "no-100% at 0.9s");
+  advance_clock(100);
+  omta_is("transform", { tx: 100 }, RunningOn.Compositor, "no-100% at 1.0s");
+  advance_clock(100);
+  omta_is_approx("transform", { tx: 50 + 50 * gTF.ease_in(0.8) },
+                 RunningOn.Compositor, 0.01, "no-100% at 1.1s");
+  advance_clock(300);
+  omta_is_approx("transform", { tx: 50 + 50 * gTF.ease_in(0.2) },
+                 RunningOn.Compositor, 0.01, "no-100% at 1.4s");
+  advance_clock(300);
+  omta_is_approx("transform", { tx: 150 - 100 * gTF.ease_in(0.6) },
+                 RunningOn.Compositor, 0.01, "no-100% at 1.7s");
+  advance_clock(200);
+  omta_is_approx("transform", { tx: 150 - 100 * gTF.ease_in(0.2) },
+                 RunningOn.Compositor, 0.01, "no-100% at 1.9s");
+  advance_clock(100);
+  omta_is("transform", { tx: 150 }, RunningOn.Compositor, "no-100% at 2.0s");
+  done_div();
+
+  // 50px at 0%, 100px at 25%, 50px at 100%
+  new_div("transform: translate(50px); " +
+          "animation: kf3 ease-out 1s alternate infinite");
+  yield waitForPaints();
+  omta_is("transform", { tx: 50 }, RunningOn.Compositor,
+          "no-0%-no-100% at 0.0s");
+  advance_clock(50);
+  omta_is_approx("transform", { tx: 50 + 50 * gTF.ease_out(0.2) },
+                 RunningOn.Compositor, 0.01, "no-0%-no-100% at 0.05s");
+  advance_clock(100);
+  omta_is_approx("transform", { tx: 50 + 50 * gTF.ease_out(0.6) },
+                 RunningOn.Compositor, 0.01, "no-0%-no-100% at 0.15s");
+  advance_clock(100);
+  omta_is("transform", { tx: "100px" }, RunningOn.Compositor,
+          "no-0%-no-100% at 0.25s");
+  advance_clock(300);
+  omta_is_approx("transform", { tx: 100 - 50 * gTF.ease_out(0.4) },
+                 RunningOn.Compositor, 0.01, "no-0%-no-100% at 0.55s");
+  advance_clock(300);
+  omta_is_approx("transform", { tx: 100 - 50 * gTF.ease_out(0.8) },
+                 RunningOn.Compositor, 0.01, "no-0%-no-100% at 0.85s");
+  advance_clock(150);
+  omta_is("transform", { tx: 50 }, RunningOn.Compositor,
+          "no-0%-no-100% at 1.0s");
+  advance_clock(150);
+  omta_is_approx("transform", { tx: 100 - 50 * gTF.ease_out(0.8) },
+                 RunningOn.Compositor, 0.01, "no-0%-no-100% at 1.15s");
+  advance_clock(450);
+  omta_is_approx("transform", { tx: 100 - 50 * gTF.ease_out(0.2) },
+                 RunningOn.Compositor, 0.01, "no-0%-no-100% at 1.6s");
+  advance_clock(250);
+  omta_is_approx("transform", { tx: 50 + 50 * gTF.ease_out(0.6) },
+                 RunningOn.Compositor, 0.01, "no-0%-no-100% at 1.85s");
+  advance_clock(100);
+  omta_is_approx("transform", { tx: 50 + 50 * gTF.ease_out(0.2) },
+                 RunningOn.Compositor, 0.01, "no-0%-no-100% at 1.95s");
+  advance_clock(50);
+  omta_is("transform", { tx: 50 }, RunningOn.Compositor,
+          "no-0%-no-100% at 2.0s");
+  done_div();
+
+  // Test that non-animatable properties are ignored.
+  // Simultaneously, test that the block is still honored, and that
+  // we still override the value when two consecutive keyframes have
+  // the same value.
+  new_div("animation: kf4 ease 10s");
+  yield waitForPaints();
+  var cs = window.getComputedStyle(gDiv);
+  is(cs.display, "block",
+     "non-animatable properties should be ignored (linear, 0s)");
+  omta_is("transform", { tx: 37 }, RunningOn.Compositor,
+          "animatable properties should still apply (linear, 0s)");
+  advance_clock(1000);
+  is(cs.display, "block",
+     "non-animatable properties should be ignored (linear, 1s)");
+  omta_is("transform", { tx: 37 }, RunningOn.Compositor,
+          "animatable properties should still apply (linear, 1s)");
+  done_div();
+  new_div("animation: kf4 step-start 10s");
+  yield waitForPaints();
+  cs = window.getComputedStyle(gDiv);
+  is(cs.display, "block",
+     "non-animatable properties should be ignored (step-start, 0s)");
+  omta_is("transform", { tx: 37 }, RunningOn.Compositor,
+          "animatable properties should still apply (step-start, 0s)");
+  advance_clock(1000);
+  is(cs.display, "block",
+     "non-animatable properties should be ignored (step-start, 1s)");
+  omta_is("transform", { tx: 37 }, RunningOn.Compositor,
+          "animatable properties should still apply (step-start, 1s)");
+  done_div();
+
+  // Test cascading of the keyframes within an @keyframes rule.
+  new_div("animation: kf_cascade1 linear 10s");
+  yield waitForPaints();
+  //    0%: 30px
+  //   50%: 20px
+  //   75%: 20px
+  //   85%: 30px
+  // 85.1%: 60px
+  //  100%: 70px
+  omta_is("transform", { tx: 30 }, RunningOn.Compositor, "kf_cascade1 at 0s");
+  advance_clock(2500);
+  omta_is("transform", { tx: 25 }, RunningOn.Compositor, "kf_cascade1 at 2.5s");
+  advance_clock(2500);
+  omta_is("transform", { tx: 20 }, RunningOn.Compositor, "kf_cascade1 at 5s");
+  advance_clock(2000);
+  omta_is("transform", { tx: 20 }, RunningOn.Compositor, "kf_cascade1 at 7s");
+  advance_clock(500);
+  omta_is("transform", { tx: 20 }, RunningOn.Compositor, "kf_cascade1 at 7.5s");
+  advance_clock(500);
+  omta_is("transform", { tx: 25 }, RunningOn.Compositor, "kf_cascade1 at 8s");
+  advance_clock(500);
+  omta_is("transform", { tx: 30 }, RunningOn.Compositor, "kf_cascade1 at 8.5s");
+  advance_clock(10);
+  // For some reason we get an error of 0.0003 for this test only
+  omta_is_approx("transform", { tx: 60 }, RunningOn.Compositor, 0.001,
+                 "kf_cascade1 at 8.51s");
+  advance_clock(745);
+  omta_is("transform", { tx: 65 }, RunningOn.Compositor,
+          "kf_cascade1 at 9.2505s");
+  done_div();
+
+  // Test cascading of the @keyframes rules themselves.
+  new_div("animation: kf_cascade2 linear 10s");
+  yield waitForPaints();
+  omta_is("opacity", 1, RunningOn.MainThread,
+          "last @keyframes rule with transform should win");
+  omta_is("transform", { tx: 100 }, RunningOn.Compositor,
+          "last @keyframes rule with transform should win");
+  done_div();
+});
+
+//----------------------------------------------------------------------
+//
+// Helper functions from test_animations.html
+//
+//----------------------------------------------------------------------
+
+function new_div(style) {
+  if (gDiv !== null) {
+    ok(false, "test author forgot to call done_div");
+  }
+  if (typeof(style) != "string") {
+    ok(false, "test author forgot to pass style argument");
+  }
+  gDiv = document.createElement("div");
+  gDiv.classList.add("target");
+  gDiv.setAttribute("style", style);
+  gDisplay.appendChild(gDiv);
+  gDiv.clientTop;
+}
+
+function done_div() {
+  if (gDiv === null) {
+    ok(false, "test author forgot to call new_div");
+  }
+  gDisplay.removeChild(gDiv);
+  gDiv = null;
+}
+
+function listen() {
+  gEventsReceived = [];
+  function listener(event) {
+    gEventsReceived.push(event);
+  }
+  gDiv.addEventListener("animationstart", listener, false);
+  gDiv.addEventListener("animationiteration", listener, false);
+  gDiv.addEventListener("animationend", listener, false);
+}
+
+function check_events(events_expected, desc) {
+  // This function checks that the list of events_expected matches
+  // the received events -- but it only checks the properties that
+  // are present on events_expected.
+  is(gEventsReceived.length, events_expected.length,
+     "number of events received for " + desc);
+  for (var i = 0,
+       i_end = Math.min(events_expected.length, gEventsReceived.length);
+       i != i_end; ++i) {
+    var exp = events_expected[i];
+    var rec = gEventsReceived[i];
+    for (var prop in exp) {
+      if (prop == "elapsedTime") {
+        // Allow floating point error.
+        ok(Math.abs(rec.elapsedTime - exp.elapsedTime) < 0.000002,
+           "events[" + i + "]." + prop + " for " + desc +
+           " received=" + rec.elapsedTime + " expected=" + exp.elapsedTime);
+      } else {
+        is(rec[prop], exp[prop], "events[" + i + "]." + prop + " for " + desc);
+      }
+    }
+  }
+  for (i = events_expected.length; i < gEventsReceived.length; ++i) {
+    ok(false, "unexpected " + gEventsReceived[i].type + " event for " + desc);
+  }
+  gEventsReceived = [];
+}
+
+function advance_clock(milliseconds) {
+  SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(milliseconds);
+}
+
+//----------------------------------------------------------------------
+//
+// Helper functions for querying the compositor thread
+//
+//----------------------------------------------------------------------
+
+// Returns a Promise that resolves once all paints have completed
+function waitForPaints() {
+  return new Promise(function(resolve, reject) {
+    waitForAllPaints(resolve);
+  });
+}
+
+// As with waitForPaints but also flushes pending style changes before waiting
+function waitForPaintsFlushed() {
+  return new Promise(function(resolve, reject) {
+    waitForAllPaintsFlushed(resolve);
+  });
+}
+
+//----------------------------------------------------------------------
+//
+// Helper functions for working with animated values
+//
+//----------------------------------------------------------------------
+
+const RunningOn = {
+  MainThread: 0,
+  Compositor: 1,
+  Either: 2
+};
+
+function omta_is(property, expected, runningOn, desc) {
+  return omta_is_approx(property, expected, runningOn, 0, desc);
+}
+
+function omta_is_approx(property, expected, runningOn, tolerance, desc) {
+  // Check input
+  const omtaProperties = [ "transform", "opacity" ];
+  if (omtaProperties.indexOf(property) === -1) {
+    ok(false, property + " is not an OMTA property");
+    return;
+  }
+  var isTransform = property == "transform";
+  var normalize = isTransform ? convertTo3dMatrix : parseFloat;
+  var compare = isTransform ?
+                matricesRoughlyEqual :
+                function(a, b, error) { return Math.abs(a - b) <= error; };
+  var normalizedToString = isTransform ?
+                           convert3dMatrixToString :
+                           JSON.stringify;
+
+  // Get actual values
+  var compositorStr = SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, property);
+  var computedStr   = window.getComputedStyle(gDiv)[property];
+
+  // Prepare expected value
+  var expectedValue = normalize(expected);
+  if (expectedValue === null) {
+    ok(false, desc + ": test author should provide a valid 'expected' value" +
+              " - got " + expected.toString());
+    return;
+  }
+
+  // Check expected value appears in the right place
+  var actualStr;
+  switch (runningOn) {
+    case RunningOn.Either:
+      runningOn = compositorStr !== "" ?
+                  RunningOn.Compositor :
+                  RunningOn.MainThread;
+      actualStr = compositorStr !== "" ? compositorStr : computedStr;
+      break;
+
+    case RunningOn.Compositor:
+      if (compositorStr === "") {
+        ok(false, desc + ": should be animating on compositor");
+        return;
+      }
+      actualStr = compositorStr;
+      break;
+
+    default:
+      if (compositorStr !== "") {
+        ok(false, desc + ": should NOT be animating on compositor");
+        return;
+      }
+      actualStr = computedStr;
+      break;
+  }
+
+  // Compare animated value with expected
+  var actualValue = normalize(actualStr);
+  if (actualValue === null) {
+    ok(false, desc + ": should return a valid result - got " + actualStr);
+    return;
+  }
+  ok(compare(expectedValue, actualValue, tolerance),
+     desc + " - got " + actualStr + ", expected " +
+     normalizedToString(expectedValue));
+
+  // For compositor animations do an additional check that they match
+  // the value calculated on the main thread
+  if (runningOn === RunningOn.Compositor) {
+    var computedValue = normalize(computedStr);
+    if (computedValue === null) {
+      ok(false, desc + ": test framework should parse computed style" +
+                " - got " + computedStr);
+      return;
+    }
+    ok(compare(computedValue, actualValue, 0),
+       desc + ": OMTA style and computed style should be equal" +
+       " - OMTA " + actualStr + ", computed " + computedStr);
+  }
+}
+
+function matricesRoughlyEqual(a, b, tolerance) {
+  tolerance = tolerance || 0.0001;
+  for (var i = 0; i < 4; i++) {
+    for (var j = 0; j < 4; j++) {
+      if (Math.abs(a[i][j] - b[i][j]) > tolerance)
+        return false;
+    }
+  }
+  return true;
+}
+
+// Converts something representing an transform into a 3d matrix in column-major
+// order.
+// The following are supported:
+//  "matrix(...)"
+//  "matrix3d(...)"
+//  [ 1, 0, 0, ... ]
+//  { a: 1, ty: 23 } etc.
+function convertTo3dMatrix(matrixLike) {
+  if (typeof(matrixLike) == "string") {
+    return convertStringTo3dMatrix(matrixLike);
+  } else if (Array.isArray(matrixLike)) {
+    return convertArrayTo3dMatrix(matrixLike);
+  } else if (typeof(matrixLike) == "object") {
+    return convertObjectTo3dMatrix(matrixLike);
+  } else {
+    return null;
+  }
+}
+
+// Converts strings of the format "matrix(...)" and "matrix3d(...)" to a 3d
+// matrix
+function convertStringTo3dMatrix(str) {
+  if (str == "none")
+    return convertArrayTo3dMatrix([1, 0, 0, 1, 0, 0]);
+  var result = str.match("^matrix(3d)?\\(");
+  if (result === null)
+    return null;
+
+  return convertArrayTo3dMatrix(
+      str.substring(result[0].length, str.length-1)
+         .split(",")
+         .map(function(component) {
+           return Number(component);
+         })
+    );
+}
+
+// Takes an array of numbers of length 6 (2d matrix) or 16 (3d matrix)
+// representing a matrix specified in column-major order and returns a 3d matrix
+// represented as an array of arrays
+function convertArrayTo3dMatrix(array) {
+  if (array.length == 6) {
+    return convertObjectTo3dMatrix(
+      { a: array[0], b: array[1],
+        c: array[2], d: array[3],
+        e: array[4], f: array[5] } );
+  } else if (array.length == 16) {
+    return [
+      array.slice(0, 3),
+      array.slice(4, 7),
+      array.slice(8, 11),
+      array.slice(12, 15)
+    ];
+  } else {
+    return null;
+  }
+}
+
+// Takes an object of the form { a: 1.1, e: 23 } and builds up a 3d matrix
+// with unspecified values filled in with identity values.
+function convertObjectTo3dMatrix(obj) {
+  return [
+    [
+      obj.a || obj.sx || obj.m11 || 1,
+      obj.b || obj.m12 || 0,
+      obj.m13 || 0,
+      obj.m14 || 0
+    ], [
+      obj.c || obj.m21 || 0,
+      obj.d || obj.sy || obj.m22 || 1,
+      obj.m23 || 0,
+      obj.m24 || 0
+    ], [
+      obj.m31 || 0,
+      obj.m32 || 0,
+      obj.sz || obj.m33 || 1,
+      obj.m34 || 0
+    ], [
+      obj.e || obj.tx || obj.m41 || 0,
+      obj.f || obj.ty || obj.m42 || 0,
+      obj.tz || obj.m43 || 0,
+      obj.m44 || 1
+    ]
+  ];
+}
+
+function convert3dMatrixToString(matrix) {
+  if (is2d(matrix)) {
+    return "matrix(" +
+           [ matrix[0][0], matrix[0][1],
+             matrix[1][0], matrix[1][1],
+             matrix[3][0], matrix[3][1] ].join(", ") + ")";
+  } else {
+    return "matrix3d(" +
+            matrix.reduce(function(outer, inner) {
+                return outer.concat(inner);
+            }).join(", ") + ")";
+  }
+}
+
+function is2d(matrix) {
+  return matrix[0][2] === 0 && matrix[0][3] === 0 &&
+         matrix[1][2] === 0 && matrix[1][3] === 0 &&
+         matrix[2][0] === 0 && matrix[2][1] === 0 &&
+         matrix[2][2] === 1 && matrix[2][3] === 0 &&
+         matrix[3][2] === 0 && matrix[3][3] === 1;
+}
+</script>
+</html>
--- a/layout/style/test/test_animations_omta_start.html
+++ b/layout/style/test/test_animations_omta_start.html
@@ -5,16 +5,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 -->
 <head>
   <meta charset="utf-8">
   <title>Test OMTA animations start correctly (Bug 975261)</title>
   <script type="application/javascript"
     src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
     src="/tests/SimpleTest/paint_listener.js"></script>
+  <script type="application/javascript" src="animation_utils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <style type="text/css">
     @keyframes anim-opacity {
        0% { opacity: 0.5 }
        100% { opacity: 0.5 }
     }
     @keyframes anim-transform {
        0% { transform: translate(50px); }
@@ -43,25 +44,19 @@ https://bugzilla.mozilla.org/show_bug.cg
   href="https://bugzilla.mozilla.org/show_bug.cgi?id=975261">Mozilla Bug
   975261</a>
 <div id="display"></div>
 <pre id="test">
 <script type="application/javascript">
 "use strict";
 
 var gUtils = SpecialPowers.DOMWindowUtils;
-var gOMTAPrefKey = "layers.offmainthreadcomposition.async-animations";
-var gOMTCEnabled = gUtils.layerManagerRemote;
 
-if (gOMTCEnabled && SpecialPowers.getBoolPref(gOMTAPrefKey)) {
-  SimpleTest.waitForExplicitFinish();
-  window.addEventListener("load", testDelay);
-} else {
-  ok(true, "OMTA not available");
-}
+SimpleTest.waitForExplicitFinish();
+runOMTATest(testDelay, SimpleTest.finish);
 
 function newTarget() {
   var target = document.createElement("div");
   target.classList.add("target");
   document.getElementById("display").appendChild(target);
   return target;
 }
 
--- a/mobile/android/base/gfx/GeckoLayerClient.java
+++ b/mobile/android/base/gfx/GeckoLayerClient.java
@@ -722,17 +722,22 @@ public class GeckoLayerClient implements
     public LayerRenderer.Frame createFrame() {
         // Create the shaders and textures if necessary.
         if (!mLayerRendererInitialized) {
             mLayerRenderer.checkMonitoringEnabled();
             mLayerRenderer.createDefaultProgram();
             mLayerRendererInitialized = true;
         }
 
-        return mLayerRenderer.createFrame(mFrameMetrics);
+        try {
+            return mLayerRenderer.createFrame(mFrameMetrics);
+        } catch (Exception e) {
+            Log.w(LOGTAG, e);
+            return null;
+        }
     }
 
     @WrapElementForJNI(allowMultithread = true)
     public void activateProgram() {
         mLayerRenderer.activateDefaultProgram();
     }
 
     @WrapElementForJNI(allowMultithread = true)
--- a/mobile/android/base/gfx/LayerRenderer.java
+++ b/mobile/android/base/gfx/LayerRenderer.java
@@ -321,16 +321,19 @@ public class LayerRenderer implements Ta
         RectF viewport = metrics.getViewport();
         RectF pageRect = metrics.getPageRect();
         float zoomFactor = metrics.zoomFactor;
 
         return createContext(new RectF(RectUtils.round(viewport)), pageRect, zoomFactor, offset);
     }
 
     private RenderContext createContext(RectF viewport, RectF pageRect, float zoomFactor, PointF offset) {
+        if (mCoordBuffer == null) {
+            throw new IllegalStateException();
+        }
         return new RenderContext(viewport, pageRect, zoomFactor, offset, mPositionHandle, mTextureHandle,
                                  mCoordBuffer);
     }
 
     private void updateDroppedFrames(long frameStartTime) {
         int frameElapsedTime = (int)((System.nanoTime() - frameStartTime) / NANOS_PER_MS);
 
         /* Update the running statistics. */
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -330,16 +330,19 @@ pref("media.audio_data.enabled", false);
 // 0 = FREE (No locking at all)
 // 1 = STANDARD (Once locked, remain locked until scrolling ends)
 // 2 = STICKY (Allow lock to be broken, with hysteresis)
 pref("apz.axis_lock_mode", 0);
 
 // Whether to print the APZC tree for debugging
 pref("apz.printtree", false);
 
+// Layerize scrollable subframes to allow async panning
+pref("apz.subframe.enabled", false);
+
 #ifdef XP_MACOSX
 // Whether to run in native HiDPI mode on machines with "Retina"/HiDPI display;
 //   <= 0 : hidpi mode disabled, display will just use pixel-based upscaling
 //   == 1 : hidpi supported if all screens share the same backingScaleFactor
 //   >= 2 : hidpi supported even with mixed backingScaleFactors (somewhat broken)
 pref("gfx.hidpi.enabled", 2);
 #endif
 
--- a/netwerk/protocol/http/Http2Stream.cpp
+++ b/netwerk/protocol/http/Http2Stream.cpp
@@ -309,16 +309,20 @@ Http2Stream::ParseHttpRequestHeaders(con
 
     Http2PushedStream *pushedStream = nullptr;
     // we remove the pushedstream from the push cache so that
     // it will not be used for another GET. This does not destroy the
     // stream itself - that is done when the transactionhash is done with it.
     if (cache)
       pushedStream = cache->RemovePushedStreamHttp2(hashkey);
 
+    LOG3(("Pushed Stream Lookup "
+          "session=%p key=%s loadgroupci=%p cache=%p hit=%p\n",
+          mSession, hashkey.get(), loadGroupCI, cache, pushedStream));
+
     if (pushedStream) {
       LOG3(("Pushed Stream Match located id=0x%X key=%s\n",
             pushedStream->StreamID(), hashkey.get()));
       pushedStream->SetConsumerStream(this);
       mPushSource = pushedStream;
       SetSentFin(true);
       AdjustPushedPriority();
 
--- a/netwerk/streamconv/converters/nsIndexedToHTML.cpp
+++ b/netwerk/streamconv/converters/nsIndexedToHTML.cpp
@@ -728,20 +728,16 @@ nsIndexedToHTML::OnIndexAvailable(nsIReq
             break;
         default:
             pushBuffer.AppendLiteral("file");
             break;
     }
 
     pushBuffer.AppendLiteral("\" href=\"");
 
-    nsXPIDLCString encoding;
-    rv = mParser->GetEncoding(getter_Copies(encoding));
-    if (NS_FAILED(rv)) return rv;
-
     // need to escape links
     nsAutoCString locEscaped;
 
     // Adding trailing slash helps to recognize whether the URL points to a file
     // or a directory (bug #214405).
     if ((type == nsIDirIndex::TYPE_DIRECTORY) && (loc.Last() != '/')) {
         loc.Append('/');
     }
@@ -749,36 +745,30 @@ nsIndexedToHTML::OnIndexAvailable(nsIReq
     // now minimally re-escape the location...
     uint32_t escFlags;
     // for some protocols, we expect the location to be absolute.
     // if so, and if the location indeed appears to be a valid URI, then go
     // ahead and treat it like one.
     if (mExpectAbsLoc &&
         NS_SUCCEEDED(net_ExtractURLScheme(loc, nullptr, nullptr, nullptr))) {
         // escape as absolute 
-        escFlags = esc_Forced | esc_OnlyASCII | esc_AlwaysCopy | esc_Minimal;
+        escFlags = esc_Forced | esc_AlwaysCopy | esc_Minimal;
     }
     else {
         // escape as relative
         // esc_Directory is needed because directories have a trailing slash.
         // Without it, the trailing '/' will be escaped, and links from within
         // that directory will be incorrect
-        escFlags = esc_Forced | esc_OnlyASCII | esc_AlwaysCopy | esc_FileBaseName | esc_Colon | esc_Directory;
+        escFlags = esc_Forced | esc_AlwaysCopy | esc_FileBaseName | esc_Colon | esc_Directory;
     }
     NS_EscapeURL(loc.get(), loc.Length(), escFlags, locEscaped);
     // esc_Directory does not escape the semicolons, so if a filename
     // contains semicolons we need to manually escape them.
     // This replacement should be removed in bug #473280
     locEscaped.ReplaceSubstring(";", "%3b");
-    if (!encoding.EqualsLiteral("UTF-8")) {
-        // Escape all non-ASCII bytes to preserve the raw value.
-        nsAutoCString outstr;
-        NS_EscapeURL(locEscaped, esc_AlwaysCopy | esc_OnlyNonASCII, outstr);
-        locEscaped = outstr;
-    }
     nsAdoptingCString htmlEscapedURL(nsEscapeHTML(locEscaped.get()));
     pushBuffer.Append(htmlEscapedURL);
 
     pushBuffer.AppendLiteral("\">");
 
     if (type == nsIDirIndex::TYPE_FILE || type == nsIDirIndex::TYPE_UNKNOWN) {
         pushBuffer.AppendLiteral("<img src=\"moz-icon://");
         int32_t lastDot = locEscaped.RFindChar('.');
--- a/nsprpub/TAG-INFO
+++ b/nsprpub/TAG-INFO
@@ -1,1 +1,1 @@
-NSPR_4_10_5_BETA2
+NSPR_4_10_5_BETA3
deleted file mode 100644
--- a/nsprpub/aclocal.m4
+++ /dev/null
@@ -1,6 +0,0 @@
-dnl
-dnl Local autoconf macros used with Mozilla.
-dnl The contents of this file are under the Public Domain.
-dnl 
-
-builtin(include, build/autoconf/acwinpaths.m4)
deleted file mode 100644
--- a/nsprpub/build/autoconf/acwinpaths.m4
+++ /dev/null
@@ -1,13 +0,0 @@
-dnl This Source Code Form is subject to the terms of the Mozilla Public
-dnl License, v. 2.0. If a copy of the MPL was not distributed with this
-dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-dnl Work around the problem that a DOS-style absolute path is split by
-dnl the colon in autoconf 2.59 and earlier. The _AC_OUTPUT_FILES macro
-dnl was removed and the problem was fixed in autoconf 2.60.
-define(GENERATE_FILES_NOSPLIT, [
-define([_AC_OUTPUT_FILES],
-       [patsubst($@, [`IFS=:], [`#IFS=:])])
-])
-m4_ifdef([_AC_OUTPUT_FILES],
-         [GENERATE_FILES_NOSPLIT(defn([_AC_OUTPUT_FILES]))])
--- a/nsprpub/config/prdepend.h
+++ b/nsprpub/config/prdepend.h
@@ -5,8 +5,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSPR in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
--- a/nsprpub/configure
+++ b/nsprpub/configure
@@ -1,16 +1,14 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68.
+# Generated by GNU Autoconf 2.69.
 #
 #
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
-# Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
 #
 #
 # This configure script is free software; the Free Software Foundation
 # gives unlimited permission to copy, distribute and modify it.
 ## -------------------- ##
 ## M4sh Initialization. ##
 ## -------------------- ##
 
@@ -129,16 +127,41 @@ PS4='+ '
 LC_ALL=C
 export LC_ALL
 LANGUAGE=C
 export LANGUAGE
 
 # CDPATH.
 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
   as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
   emulate sh
   NULLCMD=:
   # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
   # is contrary to our usage.  Disable this feature.
   alias -g '\${1+\"\$@\"}'='\"\$@\"'
   setopt NO_GLOB_SUBST
@@ -162,17 +185,18 @@ as_fn_success || { exitcode=1; echo as_f
 as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
 as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
 as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
 if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
 
 else
   exitcode=1; echo positional parameters were not saved.
 fi
-test x\$exitcode = x0 || exit 1"
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
   eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
   test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
 test \$(( 1 + 1 )) = 2 || exit 1"
   if (eval "$as_required") 2>/dev/null; then :
   as_have_required=yes
 else
@@ -207,31 +231,35 @@ done
 $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
 	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
   CONFIG_SHELL=$SHELL as_have_required=yes
 fi; }
 IFS=$as_save_IFS
 
 
       if test "x$CONFIG_SHELL" != x; then :
-  # We cannot yet assume a decent shell, so we have to provide a
-	# neutralization value for shells without unset; and this also
-	# works around shells that cannot unset nonexistent variables.
-	# Preserve -v and -x to the replacement shell.
-	BASH_ENV=/dev/null
-	ENV=/dev/null
-	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-	export CONFIG_SHELL
-	case $- in # ((((
-	  *v*x* | *x*v* ) as_opts=-vx ;;
-	  *v* ) as_opts=-v ;;
-	  *x* ) as_opts=-x ;;
-	  * ) as_opts= ;;
-	esac
-	exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
 fi
 
     if test x$as_have_required = xno; then :
   $as_echo "$0: This script requires a shell more modern than all"
   $as_echo "$0: the shells that I found on your system."
   if test x${ZSH_VERSION+set} = xset ; then
     $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
     $as_echo "$0: be upgraded to zsh 4.3.4 or later."
@@ -323,16 +351,24 @@ as_fn_mkdir_p ()
 	  s/.*/./; q'`
       test -d "$as_dir" && break
     done
     test -z "$as_dirs" || eval "mkdir $as_dirs"
   } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
 
 
 } # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
 # as_fn_append VAR VALUE
 # ----------------------
 # Append the text in VALUE to the end of the definition contained in VAR. Take
 # advantage of any shell optimizations that allow amortized linear growth over
 # repeated appends, instead of the typical quadratic growth present in naive
 # implementations.
 if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
   eval 'as_fn_append ()
@@ -444,16 +480,20 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
       :loop
       s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
       t loop
       s/-\n.*//
     ' >$as_me.lineno &&
   chmod +x "$as_me.lineno" ||
     { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
 
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
   # original and so on.  Autoconf is especially sensitive to this).
   . "./$as_me.lineno"
   # Exit status is that of the last command.
   exit
 }
 
@@ -478,59 +518,39 @@ else
   mkdir conf$$.dir 2>/dev/null
 fi
 if (echo >conf$$.file) 2>/dev/null; then
   if ln -s conf$$.file conf$$ 2>/dev/null; then
     as_ln_s='ln -s'
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
 
 if mkdir -p . 2>/dev/null; then
   as_mkdir_p='mkdir -p "$as_dir"'
 else
   test -d ./-p && rmdir ./-p
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-	test -d "$1/.";
-      else
-	case $1 in #(
-	-*)set "./$1";;
-	esac;
-	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-	???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 
 # Sed expression to map a string onto a valid variable name.
 as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
 
@@ -557,17 +577,17 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME=
 PACKAGE_TARNAME=
 PACKAGE_VERSION=
 PACKAGE_STRING=
 PACKAGE_BUGREPORT=
 PACKAGE_URL=
 
-ac_unique_file="config/libc_r.h"
+ac_unique_file="pr/include/nspr.h"
 # Factoring default headers for most tests.
 ac_includes_default="\
 #include <stdio.h>
 #ifdef HAVE_SYS_TYPES_H
 # include <sys/types.h>
 #endif
 #ifdef HAVE_SYS_STAT_H
 # include <sys/stat.h>
@@ -1264,18 +1284,16 @@ done
 build=$build_alias
 host=$host_alias
 target=$target_alias
 
 # FIXME: To remove some day.
 if test "x$host_alias" != x; then
   if test "x$build_alias" = x; then
     cross_compiling=maybe
-    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used" >&2
   elif test "x$build_alias" != "x$host_alias"; then
     cross_compiling=yes
   fi
 fi
 
 ac_tool_prefix=
 test -n "$host_alias" && ac_tool_prefix=$host_alias-
 
@@ -1570,19 +1588,19 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_
     cd "$ac_pwd" || { ac_status=$?; break; }
   done
 fi
 
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
 configure
-generated by GNU Autoconf 2.68
-
-Copyright (C) 2010 Free Software Foundation, Inc.
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
   exit
 fi
 
 ## ------------------------ ##
 ## Autoconf initialization. ##
@@ -1883,17 +1901,17 @@ eval ac_try_echo="\"\$as_me:${as_lineno-
     mv -f conftest.er1 conftest.err
   fi
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; } && {
 	 test -z "$ac_c_werror_flag" ||
 	 test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
 	 test "$cross_compiling" = yes ||
-	 $as_test_x conftest$ac_exeext
+	 test -x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
   $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
 	ac_retval=1
 fi
@@ -1973,17 +1991,17 @@ eval ac_res=\$$3
   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_func
 cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
 It was created by $as_me, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
 
 _ACEOF
 exec 5>>config.log
 {
 cat <<_ASUNAME
 ## --------- ##
@@ -2321,16 +2339,17 @@ fi
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
 ac_aux_dir=
 for ac_dir in ${srcdir}/build/autoconf "$srcdir"/${srcdir}/build/autoconf; do
   if test -f "$ac_dir/install-sh"; then
     ac_aux_dir=$ac_dir
     ac_install_sh="$ac_aux_dir/install-sh -c"
     break
   elif test -f "$ac_dir/install.sh"; then
     ac_aux_dir=$ac_dir
@@ -2461,17 +2480,16 @@ case $target_os in *\ *) target_os=`echo
 
 # The aliases save the names the user supplied, while $host etc.
 # will get canonicalized.
 test -n "$target_alias" &&
   test "$program_prefix$program_suffix$program_transform_name" = \
     NONENONEs,x,x, &&
   program_prefix=${target_alias}-
 
-
 MOD_MAJOR_VERSION=4
 MOD_MINOR_VERSION=10
 MOD_PATCH_VERSION=5
 NSPR_MODNAME=nspr20
 _HAVE_PTHREADS=
 USE_PTHREADS=
 USE_USER_PTHREADS=
 USE_NSPR_THREADS=
@@ -2529,17 +2547,17 @@ else
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -3057,17 +3075,17 @@ else
   ;;
   *)
   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_WHOAMI="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -3143,17 +3161,17 @@ else
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -3193,17 +3211,17 @@ else
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -3233,17 +3251,17 @@ else
   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -3286,17 +3304,17 @@ else
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -3327,17 +3345,17 @@ else
 else
   ac_prog_rejected=no
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
      fi
     ac_cv_prog_CC="cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
@@ -3385,17 +3403,17 @@ else
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -3429,17 +3447,17 @@ else
   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -3875,18 +3893,17 @@ if ${ac_cv_prog_cc_c89+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_cv_prog_cc_c89=no
 ac_save_CC=$CC
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
 static char *e (p, i)
      char **p;
      int i;
 {
   return p[i];
@@ -3982,17 +3999,17 @@ else
   ac_cv_prog_CXX="$CXX" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CXX="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4036,17 +4053,17 @@ else
   ac_cv_prog_CXX="$CXX" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4080,17 +4097,17 @@ else
   ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CXX="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4292,17 +4309,17 @@ else
   ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_RANLIB="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4335,17 +4352,17 @@ else
   ac_cv_prog_AR="$AR" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AR="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4378,17 +4395,17 @@ else
   ac_cv_prog_AS="$AS" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AS="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4421,17 +4438,17 @@ else
   ac_cv_prog_LD="$LD" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_LD="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4464,17 +4481,17 @@ else
   ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_STRIP="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4507,17 +4524,17 @@ else
   ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_WINDRES="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4557,17 +4574,17 @@ else
   ac_cv_prog_HOST_CC="$HOST_CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_HOST_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4656,17 +4673,17 @@ else
   ac_cv_prog_CXX="$CXX" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4700,17 +4717,17 @@ else
   ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CXX="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -4887,17 +4904,347 @@ fi
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
         fi
     fi
-    ac_ext=c
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+    for ac_prog in as
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_AS+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $AS in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_AS="$AS" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_AS="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+AS=$ac_cv_path_AS
+if test -n "$AS"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5
+$as_echo "$AS" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AS" && break
+done
+test -n "$AS" || AS="$CC"
+
+    for ac_prog in ar
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $AR in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_AR="$AR" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+AR=$ac_cv_path_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AR" && break
+done
+test -n "$AR" || AR="echo not_ar"
+
+    for ac_prog in ld link
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_LD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $LD in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LD="$LD" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_LD="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+LD=$ac_cv_path_LD
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$LD" && break
+done
+test -n "$LD" || LD="echo not_ld"
+
+    for ac_prog in strip
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $STRIP in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+STRIP=$ac_cv_path_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$STRIP" && break
+done
+test -n "$STRIP" || STRIP="echo not_strip"
+
+    for ac_prog in windres
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_WINDRES+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $WINDRES in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_WINDRES="$WINDRES" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_WINDRES="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+WINDRES=$ac_cv_path_WINDRES
+if test -n "$WINDRES"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5
+$as_echo "$WINDRES" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$WINDRES" && break
+done
+test -n "$WINDRES" || WINDRES="echo not_windres"
+
+    if test -z "$HOST_CC"; then
+        HOST_CC="$CC"
+    fi
+    if test -z "$HOST_CFLAGS"; then
+        HOST_CFLAGS="$CFLAGS"
+    fi
+fi
+
+ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
 $as_echo_n "checking how to run the C preprocessor... " >&6; }
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
@@ -5024,345 +5371,16 @@ See \`config.log' for more details" "$LI
 fi
 
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
-    if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RANLIB+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$RANLIB"; then
-  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
-  ac_ct_RANLIB=$RANLIB
-  # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_RANLIB"; then
-  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ac_ct_RANLIB="ranlib"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_RANLIB" = x; then
-    RANLIB=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    RANLIB=$ac_ct_RANLIB
-  fi
-else
-  RANLIB="$ac_cv_prog_RANLIB"
-fi
-
-    for ac_prog in as
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_AS+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $AS in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_AS="$AS" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_path_AS="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-AS=$ac_cv_path_AS
-if test -n "$AS"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5
-$as_echo "$AS" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$AS" && break
-done
-test -n "$AS" || AS="$CC"
-
-    for ac_prog in ar
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_AR+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $AR in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_AR="$AR" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-AR=$ac_cv_path_AR
-if test -n "$AR"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
-$as_echo "$AR" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$AR" && break
-done
-test -n "$AR" || AR="echo not_ar"
-
-    for ac_prog in ld link
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_LD+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $LD in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_LD="$LD" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_path_LD="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-LD=$ac_cv_path_LD
-if test -n "$LD"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
-$as_echo "$LD" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$LD" && break
-done
-test -n "$LD" || LD="echo not_ld"
-
-    for ac_prog in strip
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_STRIP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $STRIP in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-STRIP=$ac_cv_path_STRIP
-if test -n "$STRIP"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
-$as_echo "$STRIP" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$STRIP" && break
-done
-test -n "$STRIP" || STRIP="echo not_strip"
-
-    for ac_prog in windres
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_WINDRES+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $WINDRES in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_WINDRES="$WINDRES" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_path_WINDRES="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-WINDRES=$ac_cv_path_WINDRES
-if test -n "$WINDRES"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5
-$as_echo "$WINDRES" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$WINDRES" && break
-done
-test -n "$WINDRES" || WINDRES="echo not_windres"
-
-    if test -z "$HOST_CC"; then
-        HOST_CC="$CC"
-    fi
-    if test -z "$HOST_CFLAGS"; then
-        HOST_CFLAGS="$CFLAGS"
-    fi
-fi
 
 if test "$GCC" = "yes"; then
     GNU_CC=1
 fi
 if test "$GXX" = "yes"; then
     GNU_CXX=1
 fi
 if test "`echo | $AS -v 2>&1 | grep -c GNU`" != "0"; then
@@ -5551,17 +5569,17 @@ else
   ;;
   *)
   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -6037,17 +6055,17 @@ else
   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_prog in grep ggrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+      as_fn_executable_p "$ac_path_GREP" || continue
 # Check for GNU ac_path_GREP and select it if it is found.
   # Check for GNU $ac_path_GREP
 case `"$ac_path_GREP" --version 2>&1` in
 *GNU*)
   ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
 *)
   ac_count=0
   $as_echo_n 0123456789 >"conftest.in"
@@ -6103,17 +6121,17 @@ else
   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_prog in egrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+      as_fn_executable_p "$ac_path_EGREP" || continue
 # Check for GNU ac_path_EGREP and select it if it is found.
   # Check for GNU $ac_path_EGREP
 case `"$ac_path_EGREP" --version 2>&1` in
 *GNU*)
   ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
 *)
   ac_count=0
   $as_echo_n 0123456789 >"conftest.in"
@@ -7897,17 +7915,16 @@ if eval test \"x\$"$as_ac_var"\" = x"yes
 
 fi
 done
 
 LIBS="$_SAVE_LIBS"
 
 
 
-
 # Check whether --with-ccache was given.
 if test "${with_ccache+set}" = set; then :
   withval=$with_ccache; CCACHE=$withval
 else
   CCACHE="no"
 fi
 
 
@@ -7936,17 +7953,17 @@ else
   ;;
   *)
   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_CCACHE="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
   done
 IFS=$as_save_IFS
 
@@ -9140,26 +9157,26 @@ else
   mkdir conf$$.dir 2>/dev/null
 fi
 if (echo >conf$$.file) 2>/dev/null; then
   if ln -s conf$$.file conf$$ 2>/dev/null; then
     as_ln_s='ln -s'
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
 
 
 # as_fn_mkdir_p
 # -------------
 # Create "$as_dir" as a directory, including parents if necessary.
@@ -9209,38 +9226,26 @@ as_fn_mkdir_p ()
 } # as_fn_mkdir_p
 if mkdir -p . 2>/dev/null; then
   as_mkdir_p='mkdir -p "$as_dir"'
 else
   test -d ./-p && rmdir ./-p
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-	test -d "$1/.";
-      else
-	case $1 in #(
-	-*)set "./$1";;
-	esac;
-	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-	???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 
 # Sed expression to map a string onto a valid variable name.
 as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
 
@@ -9252,17 +9257,17 @@ exec 6>&1
 test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
 
 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # Save the log message, to keep $0 and so on meaningful, and to
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
 This file was extended by $as_me, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
   CONFIG_LINKS    = $CONFIG_LINKS
   CONFIG_COMMANDS = $CONFIG_COMMANDS
   $ $0 $@
 
 on `(hostname || uname -n) 2>/dev/null | sed 1q`
@@ -9309,20 +9314,20 @@ Configuration commands:
 
 Report bugs to the package provider."
 
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
 config.status
-configured by $0, generated by GNU Autoconf 2.68,
+configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
 ac_pwd='$ac_pwd'
 srcdir='$srcdir'
 test -n "\$AWK" || AWK=awk
 _ACEOF
 
@@ -9389,17 +9394,17 @@ ac_configure_extra_args=
 if $ac_cs_silent; then
   exec 6>/dev/null
   ac_configure_extra_args="$ac_configure_extra_args --silent"
 fi
 
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 if \$ac_cs_recheck; then
-  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
   shift
   \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
   CONFIG_SHELL='$SHELL'
   export CONFIG_SHELL
   exec "\$@"
 fi
 
 _ACEOF
--- a/nsprpub/configure.in
+++ b/nsprpub/configure.in
@@ -1,19 +1,20 @@
 dnl -*- Mode: Autoconf; tab-width: 4; indent-tabs-mode: nil; -*-
 dnl 
 dnl This Source Code Form is subject to the terms of the Mozilla Public
 dnl License, v. 2.0. If a copy of the MPL was not distributed with this
 dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-AC_PREREQ(2.56)
-AC_INIT(config/libc_r.h)
+AC_PREREQ(2.61)
+AC_INIT
+AC_CONFIG_SRCDIR([pr/include/nspr.h])
 
 AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf)
-AC_CANONICAL_SYSTEM
+AC_CANONICAL_TARGET
 
 dnl ========================================================
 dnl = Defaults
 dnl ========================================================
 MOD_MAJOR_VERSION=4
 MOD_MINOR_VERSION=10
 MOD_PATCH_VERSION=5
 NSPR_MODNAME=nspr20
@@ -668,31 +669,32 @@ if test "$target" != "$host" -o -n "$CRO
 else
     if test -n "$USE_CPLUS"; then
         if test "$CC" = "cl" -a -z "$CXX"; then
             CXX=$CC
         else
             AC_PROG_CXX
         fi
     fi
-    AC_PROG_CPP
     AC_PROG_RANLIB
     AC_PATH_PROGS(AS, as, $CC)
     AC_PATH_PROGS(AR, ar, echo not_ar)
     AC_PATH_PROGS(LD, ld link, echo not_ld)
     AC_PATH_PROGS(STRIP, strip, echo not_strip)
     AC_PATH_PROGS(WINDRES, windres, echo not_windres)
     if test -z "$HOST_CC"; then
         HOST_CC="$CC"
     fi
     if test -z "$HOST_CFLAGS"; then
         HOST_CFLAGS="$CFLAGS"
     fi
 fi
 
+AC_PROG_CPP
+
 if test "$GCC" = "yes"; then
     GNU_CC=1
 fi
 if test "$GXX" = "yes"; then
     GNU_CXX=1
 fi
 if test "`echo | $AS -v 2>&1 | grep -c GNU`" != "0"; then
     GNU_AS=1
@@ -2525,39 +2527,16 @@ tools are selected during the Xcode/Deve
     ;;
    
 esac
 
 if test -z "$SKIP_LIBRARY_CHECKS"; then
 dnl ========================================================
 dnl Check for system libraries
 dnl ========================================================
-dnl AC_CHECK_LIB(C, main)
-dnl AC_CHECK_LIB(C_r, main)
-dnl AC_CHECK_LIB(c, main)
-dnl AC_CHECK_LIB(c_r, main)
-dnl AC_CHECK_LIB(dce, main)
-dnl AC_CHECK_LIB(dl, main)
-dnl AC_CHECK_LIB(dld, main)
-dnl AC_CHECK_LIB(gen, main)
-dnl AC_CHECK_LIB(ip6, main)
-dnl AC_CHECK_LIB(l, main)
-dnl AC_CHECK_LIB(m, main)
-dnl AC_CHECK_LIB(nsl, main)
-dnl AC_CHECK_LIB(posix4, main)
-dnl AC_CHECK_LIB(prstrms, main)
-dnl AC_CHECK_LIB(prstrms_shr, main)
-dnl AC_CHECK_LIB(pthread, main)
-dnl AC_CHECK_LIB(pthreads, main)
-dnl AC_CHECK_LIB(resolv, main)
-dnl AC_CHECK_LIB(rt, main)
-dnl AC_CHECK_LIB(socket, main)
-dnl AC_CHECK_LIB(svld, main)
-dnl AC_CHECK_LIB(thread, main)
-dnl AC_CHECK_LIB(vms_jackets, main)
 
 
 dnl We don't want anything to link with libdl even if it's present on OS X, 
 dnl since it's not used and not part of the default installation.
 dnl The same goes for BeOS.
 dnl OS/2 has dlfcn in libc.
 
 case $target in
@@ -2569,54 +2548,30 @@ case $target in
             OS_LIBS="-ldl $OS_LIBS")])
     ;;
 esac
 
 
 dnl ========================================================
 dnl Check for system header files.
 dnl ========================================================
-dnl AC_HEADER_DIRENT
-dnl AC_HEADER_STDC
-dnl AC_HEADER_SYS_WAIT
-dnl AC_CHECK_HEADERS(fcntl.h limits.h sys/file.h sys/ioctl.h sys/time.h unistd.h)
 
 dnl ========================================================
 dnl Check for typedefs and structs
 dnl ========================================================
-dnl AC_C_CONST
-dnl AC_TYPE_UID_T
-dnl AC_TYPE_MODE_T
-dnl AC_TYPE_OFF_T
-dnl AC_TYPE_PID_T
-dnl AC_TYPE_SIZE_T
-dnl AC_STRUCT_ST_BLKSIZE
-dnl AC_STRUCT_ST_BLOCKS
-dnl AC_STRUCT_ST_RDEV
-dnl AC_HEADER_TIME
-dnl AC_STRUCT_TM
 
 dnl ========================================================
 dnl Checks for library functions.
 dnl ========================================================
 AC_PROG_GCC_TRADITIONAL
 _SAVE_LIBS="$LIBS"
 LIBS="$LIBS $OS_LIBS"
 AC_CHECK_FUNCS(dladdr gettid lchown setpriority strerror syscall)
 LIBS="$_SAVE_LIBS"
 
-dnl AC_FUNC_MEMCMP
-dnl AC_FUNC_MMAP
-dnl AC_FUNC_SETVBUF_REVERSED
-dnl AC_FUNC_STRCOLL
-dnl AC_FUNC_STRFTIME
-dnl AC_FUNC_UTIME_NULL
-dnl AC_FUNC_VPRINTF
-dnl AC_CHECK_FUNCS(ftime getcwd gethostname gettimeofday getwd mkdir mktime putenv rmdir select socket strdup strerror strstr strtol strtoul uname)
-
 dnl ========================================================
 dnl Check options
 dnl ========================================================
 
 dnl ======================================================
 dnl = Enable compiling with ccache
 dnl ======================================================
 AC_ARG_WITH(ccache,
@@ -3267,9 +3222,11 @@ if test -n "$USE_CPLUS"; then
     MAKEFILES="$MAKEFILES
         pr/src/cplus/Makefile
         pr/src/cplus/tests/Makefile
     "
 fi
 
 echo $MAKEFILES > unallmakefiles
 
-AC_OUTPUT([$MAKEFILES], [chmod +x config/nspr-config])
+AC_CONFIG_FILES([$MAKEFILES])
+AC_CONFIG_COMMANDS([default], [chmod +x config/nspr-config])
+AC_OUTPUT
--- a/nsprpub/pr/include/md/_linux.h
+++ b/nsprpub/pr/include/md/_linux.h
@@ -131,16 +131,28 @@ extern PRInt32 _PR_ppc_AtomicIncrement(P
 extern PRInt32 _PR_ppc_AtomicDecrement(PRInt32 *val);
 #define _MD_ATOMIC_DECREMENT          _PR_ppc_AtomicDecrement
 extern PRInt32 _PR_ppc_AtomicAdd(PRInt32 *ptr, PRInt32 val);
 #define _MD_ATOMIC_ADD                _PR_ppc_AtomicAdd
 extern PRInt32 _PR_ppc_AtomicSet(PRInt32 *val, PRInt32 newval);
 #define _MD_ATOMIC_SET                _PR_ppc_AtomicSet
 #endif
 
+#if defined(__powerpc64__)
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
+/* Use GCC built-in functions */
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC()
+#define _MD_ATOMIC_INCREMENT(ptr) __sync_add_and_fetch(ptr, 1)
+#define _MD_ATOMIC_DECREMENT(ptr) __sync_sub_and_fetch(ptr, 1)
+#define _MD_ATOMIC_ADD(ptr, i) __sync_add_and_fetch(ptr, i)
+#define _MD_ATOMIC_SET(ptr, nv) __sync_lock_test_and_set(ptr, nv)
+#endif
+#endif
+
 #if defined(__alpha)
 #define _PR_HAVE_ATOMIC_OPS
 #define _MD_INIT_ATOMIC()
 #define _MD_ATOMIC_ADD(ptr, i) ({               \
     PRInt32 __atomic_tmp, __atomic_ret;   \
     __asm__ __volatile__(                       \
     "1: ldl_l   %[ret], %[val]          \n"     \
     "   addl    %[ret], %[inc], %[tmp]  \n"     \
--- a/nsprpub/pr/include/pratom.h
+++ b/nsprpub/pr/include/pratom.h
@@ -102,17 +102,17 @@ long __cdecl _InterlockedExchangeAdd(lon
 
 #elif ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && \
       ((defined(__APPLE__) && \
            (defined(__ppc__) || defined(__i386__) || defined(__x86_64__))) || \
        (defined(__linux__) && \
            ((defined(__i386__) && \
            defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) || \
            defined(__ia64__) || defined(__x86_64__) || \
-           (defined(__powerpc__) && !defined(__powerpc64__)) || \
+           defined(__powerpc__) || \
            (defined(__arm__) && \
            defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) || \
            defined(__aarch64__) || defined(__alpha))))
 
 /*
  * Because the GCC manual warns that some processors may support
  * reduced functionality of __sync_lock_test_and_set, we test for the
  * processors that we believe support a full atomic exchange operation.
--- a/nsprpub/pr/src/md/windows/w95io.c
+++ b/nsprpub/pr/src/md/windows/w95io.c
@@ -85,17 +85,16 @@ PRStatus
 
     PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
         INFINITE : PR_IntervalToMilliseconds(ticks);
     rv = WaitForSingleObject(thread->md.blocked_sema, msecs);
     switch(rv) 
     {
         case WAIT_OBJECT_0:
             return PR_SUCCESS;
-            break;
         case WAIT_TIMEOUT:
             _PR_THREAD_LOCK(thread);
             if (thread->state == _PR_IO_WAIT) {
 			  ;
             } else {
                 if (thread->wait.cvar != NULL) {
                     thread->wait.cvar = NULL;
                     _PR_THREAD_UNLOCK(thread);
@@ -105,20 +104,18 @@ PRStatus
                      * call WaitForSingleObject() to clear the semaphore.
                      */
                     _PR_THREAD_UNLOCK(thread);
                     rv = WaitForSingleObject(thread->md.blocked_sema, 0);
                     PR_ASSERT(rv == WAIT_OBJECT_0);
                 }
             }
             return PR_SUCCESS;
-            break;
         default:
             return PR_FAILURE;
-            break;
     }
 }
 PRStatus
 _PR_MD_WAKEUP_WAITER(PRThread *thread)
 {
     if ( _PR_IS_NATIVE_THREAD(thread) ) 
     {
         if (ReleaseSemaphore(thread->md.blocked_sema, 1, NULL) == FALSE)
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
@@ -786,17 +786,23 @@ this.DownloadIntegration = {
       // If launch also fails (probably because it's not implemented), let
       // the OS handler try to open the parent.
       gExternalProtocolService.loadUrl(NetUtil.newURI(parent));
       yield undefined;
     }.bind(this));
 
     if (this.dontOpenFileAndFolder) {
       deferred.then((value) => { this._deferTestShowDir.resolve("success"); },
-                    (error) => { this._deferTestShowDir.reject(error); });
+                    (error) => {
+                      // Ensure that _deferTestShowDir has at least one consumer
+                      // for the error, otherwise the error will be reported as
+                      // uncaught.
+                      this._deferTestShowDir.promise.then(null, function() {});
+                      this._deferTestShowDir.reject(error);
+                    });
     }
 
     return deferred;
   },
 
   /**
    * Calls the directory service, create a downloads directory and returns an
    * nsIFile for the downloads directory.
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -2391,19 +2391,18 @@ nsWindow::DrawWindowUnderlay(LayerManage
 
     mozilla::widget::android::GeckoLayerClient* client = AndroidBridge::Bridge()->GetLayerClient();
     if (!client || client->isNull()) {
         ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return;
     }
 
     jobject frameObj = client->CreateFrame();
-    NS_ABORT_IF_FALSE(frameObj, "No frame object!");
     if (!frameObj) {
-        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
+        NS_WARNING("Warning: unable to obtain a LayerRenderer frame; aborting window underlay draw");
         return;
     }
 
     mLayerRendererFrame.Init(env, frameObj);
     if (!WidgetPaintsBackground()) {
         return;
     }
 
@@ -2420,18 +2419,20 @@ nsWindow::DrawWindowUnderlay(LayerManage
 void
 nsWindow::DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect)
 {
     PROFILER_LABEL("nsWindow", "DrawWindowOverlay");
     JNIEnv *env = GetJNIForThread();
 
     AutoLocalJNIFrame jniFrame(env);
 
-    NS_ABORT_IF_FALSE(!mLayerRendererFrame.isNull(),
-                      "Frame should have been created in DrawWindowUnderlay()!");
+    if (mLayerRendererFrame.isNull()) {
+        NS_WARNING("Warning: do not have a LayerRenderer frame; aborting window overlay draw");
+        return;
+    }
 
     mozilla::widget::android::GeckoLayerClient* client = AndroidBridge::Bridge()->GetLayerClient();
 
     gl::GLContext* gl = static_cast<CompositorOGL*>(aManager->GetCompositor())->gl();
     gl::ScopedGLState scopedScissorTestState(gl, LOCAL_GL_SCISSOR_TEST);
     gl::ScopedScissorRect scopedScissorRectState(gl);
 
     client->ActivateProgram();