Merge TM -> JM
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 01 Jun 2011 11:22:03 -0700
changeset 75130 2fd70a4a2df02c9b243b026b256482f8c385ac63
parent 75129 8a0b550c10eb389db18d09ae33c75e38a2f9acdd (current diff)
parent 70641 f8c79845996f59017c26a77bfbac255858ae172b (diff)
child 75131 cbd95be079612742815f98591394a58bac656960
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone6.0a1
Merge TM -> JM
js/src/jit-test/jit_test.py
js/src/jscntxt.h
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsgcmark.cpp
js/src/jsstr.cpp
js/src/methodjit/StubCalls.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcwrappednative.cpp
--- a/dom/src/threads/nsDOMWorker.cpp
+++ b/dom/src/threads/nsDOMWorker.cpp
@@ -909,17 +909,16 @@ nsDOMWorkerScope::PostCreate(nsIXPConnec
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWorkerScope::Trace(nsIXPConnectWrappedNative* /* aWrapper */,
                         JSTracer* aTracer,
                         JSObject* /*aObj */)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   nsDOMWorkerMessageHandler::Trace(aTracer);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWorkerScope::Finalize(nsIXPConnectWrappedNative* /* aWrapper */,
                            JSContext* /* aCx */,
                            JSObject* /* aObj */)
@@ -1504,18 +1503,16 @@ nsDOMWorker::PostCreate(nsIXPConnectWrap
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWorker::Trace(nsIXPConnectWrappedNative* /* aWrapper */,
                    JSTracer* aTracer,
                    JSObject* /*aObj */)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
   PRBool canceled = PR_FALSE;
   {
     MutexAutoLock lock(mLock);
     canceled = mStatus == eKilled;
   }
 
   if (!canceled) {
     nsDOMWorkerMessageHandler::Trace(aTracer);
--- a/dom/src/threads/nsDOMWorkerXHR.cpp
+++ b/dom/src/threads/nsDOMWorkerXHR.cpp
@@ -425,18 +425,16 @@ NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(
 
 #include "xpc_map_end.h"
 
 NS_IMETHODIMP
 nsDOMWorkerXHR::Trace(nsIXPConnectWrappedNative* /* aWrapper */,
                       JSTracer* aTracer,
                       JSObject* /*aObj */)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
   if (!mCanceled) {
     nsDOMWorkerMessageHandler::Trace(aTracer);
     if (mUpload) {
       mUpload->Trace(aTracer);
     }
   }
 
   return NS_OK;
--- a/js/src/assembler/wtf/Platform.h
+++ b/js/src/assembler/wtf/Platform.h
@@ -1003,21 +1003,16 @@
 #define ENABLE_REPAINT_THROTTLING 0
 #endif
 
 /* Disable the JIT on versions of GCC prior to 4.1 */
 #if !defined(ENABLE_JIT) && WTF_COMPILER_GCC && !GCC_VERSION_AT_LEAST(4, 1, 0)
 #define ENABLE_JIT 0
 #endif
 
-/* JIT is not implemented for 64 bit on MSVC */
-#if !defined(ENABLE_JIT) && WTF_COMPILER_MSVC && WTF_CPU_X86_64
-#define ENABLE_JIT 0
-#endif
-
 /* The JIT is enabled by default on all x86, x64-64, ARM & MIPS platforms. */
 #if !defined(ENABLE_JIT) \
     && (WTF_CPU_X86 || WTF_CPU_X86_64 || WTF_CPU_ARM || WTF_CPU_MIPS) \
     && (WTF_OS_DARWIN || !WTF_COMPILER_GCC || GCC_VERSION_AT_LEAST(4, 1, 0)) \
     && !WTF_OS_WINCE
 #define ENABLE_JIT 1
 #endif
 
--- a/js/src/jit-test/jit_test.py
+++ b/js/src/jit-test/jit_test.py
@@ -322,17 +322,17 @@ def run_tests(tests, test_dir, lib_dir, 
             except IOError:
                 sys.stderr.write("Exception thrown trying to write failure file '%s'\n"%
                                  OPTIONS.write_failures)
                 traceback.print_exc()
                 sys.stderr.write('---\n')
 
         def show_test(test):
             if OPTIONS.show_failed:
-                print('    ' + subprocess.list2cmdline(get_test_cmd(test.path, test.jitflags, lib_dir)))
+                print('    ' + subprocess.list2cmdline(get_test_cmd(test.path, test.jitflags, lib_dir, shell_args)))
             else:
                 print('    ' + ' '.join(test.jitflags + [ test.path ]))
 
         print('FAILURES:')
         for test, _, __, ___, timed_out in failures:
             if not timed_out:
                 show_test(test)
 
@@ -489,30 +489,30 @@ def main(argv):
     jitflags_list = parse_jitflags()
     for test in test_list:
         for jitflags in jitflags_list:
             new_test = test.copy()
             new_test.jitflags.extend(jitflags)
             job_list.append(new_test)
     
 
+    shell_args = shlex.split(OPTIONS.shell_args)
+
     if OPTIONS.debug:
         if len(job_list) > 1:
             print('Multiple tests match command line arguments, debugger can only run one')
             for tc in job_list:
                 print('    %s'%tc.path)
             sys.exit(1)
 
         tc = job_list[0]
-        cmd = [ 'gdb', '--args' ] + get_test_cmd(tc.path, tc.jitflags, lib_dir)
+        cmd = [ 'gdb', '--args' ] + get_test_cmd(tc.path, tc.jitflags, lib_dir, shell_args)
         call(cmd)
         sys.exit()
 
-    shell_args = shlex.split(OPTIONS.shell_args)
-
     try:
         ok = run_tests(job_list, test_dir, lib_dir, shell_args)
         if not ok:
             sys.exit(2)
     except OSError:
         if not os.path.exists(JS):
             print >> sys.stderr, "JS shell argument: file does not exist: '%s'"%JS
             sys.exit(1)
--- a/js/src/jit-test/tests/basic/testBug614653.js
+++ b/js/src/jit-test/tests/basic/testBug614653.js
@@ -1,10 +1,10 @@
 /* Bug 614653 - This test .2 seconds with the fix, 20 minutes without. */
-for (var i = 0; i < 100; ++i) {
+for (var i = 0; i < 10; ++i) {
     var arr = [];
     var s = "abcdefghijklmnop";
-    for (var i = 0; i < 50000; ++i) {
+    for (var j = 0; j < 50000; ++j) {
         s = "<" + s + ">";
         arr.push(s);
     }
     gc();
 }
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testRopeMarking.js
@@ -0,0 +1,13 @@
+for (var i = 0; i < 10; ++i) {
+    var arr = [];
+    var s = "abcdefghijklmnop";
+    for (var j = 0; j < 5000; ++j) {
+        s = "<" + s + ">";
+        arr.push(s);
+    }
+    gc();
+    for (var j = 0; j < 5000; ++j) {
+        arr[j].search("a");
+    }
+    gc();
+}
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -422,16 +422,17 @@ struct JSRuntime {
     js::GCMarker        *gcMarkingTracer;
     int64               gcJitReleaseTime;
     JSGCMode            gcMode;
     volatile bool       gcIsNeeded;
     JSObject           *gcWeakMapList;
 
     /* Pre-allocated space for the GC mark stacks. Pointer type ensures alignment. */
     void                *gcMarkStackObjs[js::OBJECT_MARK_STACK_SIZE / sizeof(void *)];
+    void                *gcMarkStackRopes[js::ROPES_MARK_STACK_SIZE / sizeof(void *)];
     void                *gcMarkStackXMLs[js::XML_MARK_STACK_SIZE / sizeof(void *)];
     void                *gcMarkStackLarges[js::LARGE_MARK_STACK_SIZE / sizeof(void *)];
 
     /*
      * Compartment that triggered GC. If more than one Compatment need GC,
      * gcTriggerCompartment is reset to NULL and a global GC is performed.
      */
     JSCompartment       *gcTriggerCompartment;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1509,16 +1509,17 @@ namespace js {
  * arenas to the stack as necessary while markDelayedChildren pops the arenas
  * from the stack until it empties.
  */
 
 GCMarker::GCMarker(JSContext *cx)
   : color(0),
     unmarkedArenaStackTop(MarkingDelay::stackBottom()),
     objStack(cx->runtime->gcMarkStackObjs, sizeof(cx->runtime->gcMarkStackObjs)),
+    ropeStack(cx->runtime->gcMarkStackRopes, sizeof(cx->runtime->gcMarkStackRopes)),
     xmlStack(cx->runtime->gcMarkStackXMLs, sizeof(cx->runtime->gcMarkStackXMLs)),
     largeStack(cx->runtime->gcMarkStackLarges, sizeof(cx->runtime->gcMarkStackLarges))
 {
     JS_TRACER_INIT(this, cx, NULL);
 #ifdef DEBUG
     markLaterArenas = 0;
 #endif
 #ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1180,16 +1180,17 @@ struct LargeMarkItem
 {
     JSObject *obj;
     uintN markpos;
 
     LargeMarkItem(JSObject *obj) : obj(obj), markpos(0) {}
 };
 
 static const size_t OBJECT_MARK_STACK_SIZE = 32768 * sizeof(JSObject *);
+static const size_t ROPES_MARK_STACK_SIZE = 1024 * sizeof(JSString *);
 static const size_t XML_MARK_STACK_SIZE = 1024 * sizeof(JSXML *);
 static const size_t LARGE_MARK_STACK_SIZE = 64 * sizeof(LargeMarkItem);
 
 struct GCMarker : public JSTracer {
   private:
     /* The color is only applied to objects, functions and xml. */
     uint32 color;
 
@@ -1207,16 +1208,17 @@ struct GCMarker : public JSTracer {
 #ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS
     Vector<void *, 0, SystemAllocPolicy> conservativeRoots;
     const char *conservativeDumpFileName;
 
     void dumpConservativeRoots();
 #endif
 
     MarkStack<JSObject *> objStack;
+    MarkStack<JSRope *> ropeStack;
     MarkStack<JSXML *> xmlStack;
     MarkStack<LargeMarkItem> largeStack;
 
   public:
     explicit GCMarker(JSContext *cx);
     ~GCMarker();
 
     uint32 getMarkColor() const {
@@ -1229,26 +1231,34 @@ struct GCMarker : public JSTracer {
         color = newColor;
     }
 
     void delayMarkingChildren(const void *thing);
 
     void markDelayedChildren();
 
     bool isMarkStackEmpty() {
-        return objStack.isEmpty() && xmlStack.isEmpty() && largeStack.isEmpty();
+        return objStack.isEmpty() &&
+               ropeStack.isEmpty() &&
+               xmlStack.isEmpty() &&
+               largeStack.isEmpty();
     }
 
     JS_FRIEND_API(void) drainMarkStack();
 
     void pushObject(JSObject *obj) {
         if (!objStack.push(obj))
             delayMarkingChildren(obj);
     }
 
+    void pushRope(JSRope *rope) {
+        if (!ropeStack.push(rope))
+            delayMarkingChildren(rope);
+    }
+
     void pushXML(JSXML *xml) {
         if (!xmlStack.push(xml))
             delayMarkingChildren(xml);
     }
 };
 
 void
 MarkStackRangeConservatively(JSTracer *trc, Value *begin, Value *end);
--- a/js/src/jsgcmark.cpp
+++ b/js/src/jsgcmark.cpp
@@ -523,23 +523,57 @@ restart:
         PushMarkStack(gcmarker, &shape->methodObject());
 
     shape = shape->previous();
     if (shape && shape->markIfUnmarked(gcmarker->getMarkColor()))
         goto restart;
 }
 
 static inline void
+ScanRope(GCMarker *gcmarker, JSRope *rope)
+{
+    JS_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment,
+                 rope->compartment() == gcmarker->context->runtime->gcCurrentCompartment
+                 || rope->compartment() == gcmarker->context->runtime->atomsCompartment);
+    JS_ASSERT(rope->isMarked());
+
+    JSString *leftChild = NULL;
+    do {
+        JSString *rightChild = rope->rightChild();
+
+        if (rightChild->isRope()) {
+            if (rightChild->markIfUnmarked())
+                gcmarker->pushRope(&rightChild->asRope());
+        } else {
+            rightChild->asLinear().mark(gcmarker);
+        }
+        leftChild = rope->leftChild();
+
+        if (leftChild->isLinear()) {
+            leftChild->asLinear().mark(gcmarker);
+            return;
+        }
+        rope = &leftChild->asRope();
+    } while (leftChild->markIfUnmarked());
+}
+
+static inline void
 PushMarkStack(GCMarker *gcmarker, JSString *str)
 {
     JS_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment,
                  str->compartment() == gcmarker->context->runtime->gcCurrentCompartment
                  || str->compartment() == gcmarker->context->runtime->atomsCompartment);
 
-    str->mark(gcmarker);
+    if (str->isLinear()) {
+        str->asLinear().mark(gcmarker);
+    } else {
+        JS_ASSERT(str->isRope());
+        if (str->markIfUnmarked())
+            ScanRope(gcmarker, &str->asRope());
+    }
 }
 
 static const uintN LARGE_OBJECT_CHUNK_SIZE = 2048;
 
 static void
 ScanObject(GCMarker *gcmarker, JSObject *obj)
 {
     /*
@@ -703,16 +737,19 @@ MarkChildren(JSTracer *trc, JSXML *xml)
 #endif
 
 } /* namespace gc */
 
 void
 GCMarker::drainMarkStack()
 {
     while (!isMarkStackEmpty()) {
+        while (!ropeStack.isEmpty())
+            ScanRope(this, ropeStack.pop());
+
         while (!objStack.isEmpty())
             ScanObject(this, objStack.pop());
 
         while (!xmlStack.isEmpty())
             MarkChildren(this, xmlStack.pop());
 
         if (!largeStack.isEmpty()) {
             LargeMarkItem &item = largeStack.peek();
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -108,102 +108,24 @@ JSString::isFixed() const
 bool
 JSString::isExternal() const
 {
     bool is_external = arenaHeader()->getThingKind() == FINALIZE_EXTERNAL_STRING;
     JS_ASSERT_IF(is_external, isFixed());
     return is_external;
 }
 
-static JS_ALWAYS_INLINE JSString *
-Tag(JSRope *str)
-{
-    JS_ASSERT(!(size_t(str) & 1));
-    return (JSString *)(size_t(str) | 1);
-}
-
-static JS_ALWAYS_INLINE bool
-Tagged(JSString *str)
-{
-    return (size_t(str) & 1) != 0;
-}
-
-static JS_ALWAYS_INLINE JSRope *
-Untag(JSString *str)
-{
-    JS_ASSERT((size_t(str) & 1) == 1);
-    return (JSRope *)(size_t(str) & ~size_t(1));
-}
-
 void
 JSLinearString::mark(JSTracer *)
 {
     JSLinearString *str = this;
     while (!str->isStaticAtom() && str->markIfUnmarked() && str->isDependent())
         str = str->asDependent().base();
 }
 
-void
-JSString::mark(JSTracer *trc)
-{
-    if (isLinear()) {
-        asLinear().mark(trc);
-        return;
-    }
-
-    /*
-     * This function must not fail, so a simple stack-based traversal must not
-     * be used (since it may oom if the stack grows large). Instead, strings
-     * are temporarily mutated to embed parent pointers as they are traversed.
-     * This algorithm is homomorphic to JSString::flatten.
-     */
-    JSRope *str = &asRope();
-    JSRope *parent = NULL;
-    first_visit_node: {
-        if (!str->markIfUnmarked())
-            goto finish_node;
-        JS_ASSERT(!Tagged(str->d.u1.left) && !Tagged(str->d.s.u2.right));
-        JSString *left = str->d.u1.left;
-        if (left->isRope()) {
-            str->d.u1.left = Tag(parent);
-            parent = str;
-            str = &left->asRope();
-            goto first_visit_node;
-        }
-        left->asLinear().mark(trc);
-    }
-    visit_right_child: {
-        JSString *right = str->d.s.u2.right;
-        if (right->isRope()) {
-            str->d.s.u2.right = Tag(parent);
-            parent = str;
-            str = &right->asRope();
-            goto first_visit_node;
-        }
-        right->asLinear().mark(trc);
-    }
-    finish_node: {
-        if (!parent)
-            return;
-        if (Tagged(parent->d.u1.left)) {
-            JS_ASSERT(!Tagged(parent->d.s.u2.right));
-            JSRope *nextParent = Untag(parent->d.u1.left);
-            parent->d.u1.left = str;
-            str = parent;
-            parent = nextParent;
-            goto visit_right_child;
-        }
-        JSRope *nextParent = Untag(parent->d.s.u2.right);
-        parent->d.s.u2.right = str;
-        str = parent;
-        parent = nextParent;
-        goto finish_node;
-    }
-}
-
 static JS_ALWAYS_INLINE size_t
 RopeCapacityFor(size_t length)
 {
     static const size_t ROPE_DOUBLING_MAX = 1024 * 1024;
 
     /*
      * Grow by 12.5% if the buffer is very large. Otherwise, round up to the
      * next power of 2. This is similar to what we do with arrays; see
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -366,20 +366,16 @@ class JSString : public js::gc::Cell
     bool isStaticAtom() const {
         return (d.lengthAndFlags & FLAGS_MASK) == STATIC_ATOM_FLAGS;
     }
 
     /* Only called by the GC for strings with the FINALIZE_STRING kind. */
 
     inline void finalize(JSContext *cx);
 
-    /* Called during GC for any string. */
-
-    void mark(JSTracer *trc);
-
     /* Offsets for direct field from jit code. */
 
     static size_t offsetOfLengthAndFlags() {
         return offsetof(JSString, d.lengthAndFlags);
     }
 
     static size_t offsetOfChars() {
         return offsetof(JSString, d.u1.chars);
@@ -408,19 +404,20 @@ class JSRope : public JSString
     }
 };
 
 JS_STATIC_ASSERT(sizeof(JSRope) == sizeof(JSString));
 
 class JSLinearString : public JSString
 {
     friend class JSString;
+
+  public:
     void mark(JSTracer *trc);
 
-  public:
     JS_ALWAYS_INLINE
     const jschar *chars() const {
         JS_ASSERT(isLinear());
         return d.u1.chars;
     }
 };
 
 JS_STATIC_ASSERT(sizeof(JSLinearString) == sizeof(JSString));
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -1964,17 +1964,17 @@ stubs::DecGlobalName(VMFrame &f, JSAtom 
     JSObject *obj = f.fp()->scopeChain().getGlobal();
     if (!NameIncDec<-1, false, strict>(f, obj, atom))
         THROW();
 }
 
 template void JS_FASTCALL stubs::DecGlobalName<true>(VMFrame &f, JSAtom *atom);
 template void JS_FASTCALL stubs::DecGlobalName<false>(VMFrame &f, JSAtom *atom);
 
-static bool JS_FASTCALL
+static bool JS_ALWAYS_INLINE
 InlineGetProp(VMFrame &f)
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
     Value *vp = &f.regs.sp[-1];
 
     if (vp->isMagic(JS_LAZY_ARGUMENTS)) {
--- a/js/src/xpconnect/src/XPCWrapper.cpp
+++ b/js/src/xpconnect/src/XPCWrapper.cpp
@@ -130,17 +130,17 @@ Unwrap(JSContext *cx, JSObject *wrapper)
       return nsnull;
     return wrapper->unwrap();
   }
 
   return nsnull;
 }
 
 JSObject *
-UnsafeUnwrapSecurityWrapper(JSContext *cx, JSObject *obj)
+UnsafeUnwrapSecurityWrapper(JSObject *obj)
 {
   if (obj->isProxy()) {
     return obj->unwrap();
   }
 
   return obj;
 }
 
--- a/js/src/xpconnect/src/XPCWrapper.h
+++ b/js/src/xpconnect/src/XPCWrapper.h
@@ -91,14 +91,14 @@ IsSecurityWrapper(JSObject *wrapper)
  * Since this is meant to be called from functions like
  * XPCWrappedNative::GetWrappedNativeOfJSObject, it does not set an
  * exception on |cx|.
  */
 JSObject *
 Unwrap(JSContext *cx, JSObject *wrapper);
 
 JSObject *
-UnsafeUnwrapSecurityWrapper(JSContext *cx, JSObject *obj);
+UnsafeUnwrapSecurityWrapper(JSObject *obj);
 
 } // namespace XPCWrapper
 
 
 #endif
--- a/js/src/xpconnect/src/xpccomponents.cpp
+++ b/js/src/xpconnect/src/xpccomponents.cpp
@@ -3012,17 +3012,17 @@ SandboxImport(JSContext *cx, uintN argc,
         funname = JS_ValueToString(cx, argv[1]);
         if (!funname)
             return JS_FALSE;
         argv[1] = STRING_TO_JSVAL(funname);
     } else {
         // NB: funobj must only be used to get the JSFunction out.
         JSObject *funobj = JSVAL_TO_OBJECT(argv[0]);
         if (funobj->isProxy()) {
-            funobj = XPCWrapper::UnsafeUnwrapSecurityWrapper(cx, funobj);
+            funobj = XPCWrapper::UnsafeUnwrapSecurityWrapper(funobj);
         }
 
         JSAutoEnterCompartment ac;
         if (!ac.enter(cx, funobj)) {
             return JS_FALSE;
         }
 
         JSFunction *fun = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(funobj));
@@ -3555,17 +3555,17 @@ xpc_EvalInSandbox(JSContext *cx, JSObjec
             if (fp && !system) {
                 ssm->IsCapabilityEnabled("UniversalXPConnect", &system);
                 NS_ASSERTION(system, "Bad caller!");
             }
         }
     }
 #endif
 
-    sandbox = XPCWrapper::UnsafeUnwrapSecurityWrapper(cx, sandbox);
+    sandbox = XPCWrapper::UnsafeUnwrapSecurityWrapper(sandbox);
     if (!sandbox || sandbox->getJSClass() != &SandboxClass) {
         return NS_ERROR_INVALID_ARG;
     }
 
     nsIScriptObjectPrincipal *sop =
         (nsIScriptObjectPrincipal*)xpc_GetJSPrivate(sandbox);
     NS_ASSERTION(sop, "Invalid sandbox passed");
     nsCOMPtr<nsIPrincipal> prin = sop->GetPrincipal();
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -1437,20 +1437,16 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS
 // XPC_WN_Shared_Proto_Enumerate or something rather than checking for
 // 4 classes?
 #define IS_PROTO_CLASS(clazz)                                                 \
     ((clazz) == &XPC_WN_NoMods_WithCall_Proto_JSClass ||                      \
      (clazz) == &XPC_WN_NoMods_NoCall_Proto_JSClass ||                        \
      (clazz) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||                 \
      (clazz) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass)
 
-// Comes from xpcwrappednativeops.cpp
-extern void
-xpc_TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper);
-
 /***************************************************************************/
 
 namespace XPCWrapper {
 
 enum WrapperType {
     UNKNOWN         = 0,
     NONE            = 0,
     XPCNW_IMPLICIT  = 1 << 0,
@@ -2574,16 +2570,18 @@ public:
     GetUsedOnly(XPCCallContext& ccx,
                 nsISupports* Object,
                 XPCWrappedNativeScope* Scope,
                 XPCNativeInterface* Interface,
                 XPCWrappedNative** wrapper);
 
     // If pobj2 is not null and *pobj2 is not null after the call then *pobj2
     // points to an object for which IS_SLIM_WRAPPER_OBJECT is true.
+    // cx is null when invoked from the marking phase of the GC. In this case
+    // fubobj must be null as well.
     static XPCWrappedNative*
     GetWrappedNativeOfJSObject(JSContext* cx, JSObject* obj,
                                JSObject* funobj = nsnull,
                                JSObject** pobj2 = nsnull,
                                XPCWrappedNativeTearOff** pTearOff = nsnull);
     static XPCWrappedNative*
     GetAndMorphWrappedNativeOfJSObject(JSContext* cx, JSObject* obj)
     {
--- a/js/src/xpconnect/src/xpcwrappednative.cpp
+++ b/js/src/xpconnect/src/xpcwrappednative.cpp
@@ -1746,16 +1746,22 @@ XPCWrappedNative*
 XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx,
                                              JSObject* obj,
                                              JSObject* funobj,
                                              JSObject** pobj2,
                                              XPCWrappedNativeTearOff** pTearOff)
 {
     NS_PRECONDITION(obj, "bad param");
 
+    // fubobj must be null if called without cx.
+    NS_PRECONDITION(cx || !funobj, "bad param");
+
+    // *pTeaorOff must be null if pTearOff is given
+    NS_PRECONDITION(!pTearOff || !*pTearOff, "bad param");
+
     JSObject* cur;
 
     XPCWrappedNativeProto* proto = nsnull;
     nsIClassInfo* protoClassInfo = nsnull;
 
     // If we were passed a function object then we need to find the correct
     // wrapper out of those that might be in the callee obj's proto chain.
 
@@ -1765,17 +1771,17 @@ XPCWrappedNative::GetWrappedNativeOfJSOb
         OBJ_TO_INNER_OBJECT(cx, funObjParent);
         NS_ASSERTION(funObjParent, "funobj has no parent");
 
         js::Class* funObjParentClass = funObjParent->getClass();
 
         if(IS_PROTO_CLASS(funObjParentClass))
         {
             NS_ASSERTION(funObjParent->getParent(), "funobj's parent (proto) is global");
-            proto = (XPCWrappedNativeProto*) xpc_GetJSPrivate(funObjParent);
+            proto = (XPCWrappedNativeProto*) funObjParent->getPrivate();
             if(proto)
                 protoClassInfo = proto->GetClassInfo();
         }
         else if(IS_WRAPPER_CLASS(funObjParentClass))
         {
             cur = funObjParent;
             goto return_wrapper;
         }
@@ -1787,28 +1793,29 @@ XPCWrappedNative::GetWrappedNativeOfJSOb
         }
         else
         {
             NS_ERROR("function object has parent of unknown class!");
             return nsnull;
         }
     }
 
+  restart:
     for(cur = obj; cur; cur = cur->getProto())
     {
         // this is on two lines to make the compiler happy given the goto.
         js::Class* clazz;
         clazz = cur->getClass();
 
         if(IS_WRAPPER_CLASS(clazz))
         {
 return_wrapper:
             JSBool isWN = IS_WN_WRAPPER_OBJECT(cur);
             XPCWrappedNative* wrapper =
-                isWN ? (XPCWrappedNative*) xpc_GetJSPrivate(cur) : nsnull;
+                isWN ? (XPCWrappedNative*) cur->getPrivate() : nsnull;
             if(proto)
             {
                 XPCWrappedNativeProto* wrapper_proto =
                     isWN ? wrapper->GetProto() : GetSlimWrapperProto(cur);
                 if(proto != wrapper_proto &&
                    (!protoClassInfo || !wrapper_proto ||
                     protoClassInfo != wrapper_proto->GetClassInfo()))
                     continue;
@@ -1817,38 +1824,41 @@ return_wrapper:
                 *pobj2 = isWN ? nsnull : cur;
             return wrapper;
         }
 
         if(IS_TEAROFF_CLASS(clazz))
         {
 return_tearoff:
             XPCWrappedNative* wrapper =
-                (XPCWrappedNative*) xpc_GetJSPrivate(cur->getParent());
+                (XPCWrappedNative*) cur->getParent()->getPrivate();
             if(proto && proto != wrapper->GetProto() &&
                (proto->GetScope() != wrapper->GetScope() ||
                 !protoClassInfo || !wrapper->GetProto() ||
                 protoClassInfo != wrapper->GetProto()->GetClassInfo()))
                 continue;
             if(pobj2)
                 *pobj2 = nsnull;
-            XPCWrappedNativeTearOff* to =
-                (XPCWrappedNativeTearOff*) xpc_GetJSPrivate(cur);
+            XPCWrappedNativeTearOff* to = (XPCWrappedNativeTearOff*) cur->getPrivate();
             if(!to)
                 return nsnull;
             if(pTearOff)
                 *pTearOff = to;
             return wrapper;
         }
 
         // Unwrap any wrapper wrappers.
-        JSObject *unsafeObj;
-        if((unsafeObj = XPCWrapper::Unwrap(cx, cur)))
-            return GetWrappedNativeOfJSObject(cx, unsafeObj, funobj, pobj2,
-                                              pTearOff);
+        JSObject *unsafeObj = cx
+                              ? XPCWrapper::Unwrap(cx, cur)
+                              : XPCWrapper::UnsafeUnwrapSecurityWrapper(cur);
+        if(unsafeObj)
+        {
+            obj = unsafeObj;
+            goto restart;
+        }
     }
 
     if(pobj2)
         *pobj2 = nsnull;
     return nsnull;
 }
 
 JSBool
--- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp
@@ -708,18 +708,18 @@ TraceScopeJSObjects(JSTracer *trc, XPCWr
     obj = scope->GetPrototypeJSFunction();
     if(obj)
     {
         JS_CALL_OBJECT_TRACER(trc, obj,
                               "XPCWrappedNativeScope::mPrototypeJSFunction");
     }
 }
 
-void
-xpc_TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper)
+static void
+TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper)
 {
     // NOTE: It might be nice to also do the wrapper->Mark() call here too
     // when we are called during the marking phase of JS GC to mark the
     // wrapper's and wrapper's proto's interface sets.
     //
     // We currently do that in the GC callback code. The reason we don't do that
     // here is because the bits used in that marking do unpleasant things to the
     // member counts in the interface and interface set objects. Those counts
@@ -738,34 +738,46 @@ xpc_TraceForValidWrapper(JSTracer *trc, 
     // need to use the JSClass. So, some marking is required for protection.
 
     wrapper->TraceJS(trc);
      
     TraceScopeJSObjects(trc, wrapper->GetScope());
 }
 
 static void
-XPC_WN_Shared_Trace(JSTracer *trc, JSObject *obj)
+MarkWrappedNative(JSTracer *trc, JSObject *obj, bool helper)
 {
     JSObject *obj2;
+
+    // Pass null for the first JSContext* parameter  to skip any security
+    // checks and to avoid potential state change there.
     XPCWrappedNative* wrapper =
-        XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj, nsnull,
-                                                     &obj2);
+        XPCWrappedNative::GetWrappedNativeOfJSObject(nsnull, obj, nsnull, &obj2);
 
     if(wrapper)
     {
         if(wrapper->IsValid())
-             xpc_TraceForValidWrapper(trc, wrapper);
+        {
+            if(helper)
+                wrapper->GetScriptableCallback()->Trace(wrapper, trc, obj);
+             TraceForValidWrapper(trc, wrapper);
+        }
     }
     else if(obj2)
     {
         GetSlimWrapperProto(obj2)->TraceJS(trc);
     }
 }
 
+static void
+XPC_WN_Shared_Trace(JSTracer *trc, JSObject *obj)
+{
+    MarkWrappedNative(trc, obj, false);
+}
+
 static JSBool
 XPC_WN_NoHelper_Resolve(JSContext *cx, JSObject *obj, jsid id)
 {
     MORPH_SLIM_WRAPPER(cx, obj);
     XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, id);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
@@ -1093,32 +1105,17 @@ XPC_WN_Helper_Finalize(JSContext *cx, JS
         return;
     wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj);
     wrapper->FlatJSObjectFinalized(cx);
 }
 
 static void
 XPC_WN_Helper_Trace(JSTracer *trc, JSObject *obj)
 {
-    JSObject *obj2;
-    XPCWrappedNative* wrapper =
-        XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj, nsnull,
-                                                     &obj2);
-    if(wrapper)
-    {
-        if(wrapper->IsValid())
-        {
-            wrapper->GetScriptableCallback()->Trace(wrapper, trc, obj);
-            xpc_TraceForValidWrapper(trc, wrapper);
-        }
-    }
-    else if(obj2)
-    {
-        GetSlimWrapperProto(obj2)->TraceJS(trc);
-    }
+    MarkWrappedNative(trc, obj, true);
 }
 
 static JSBool
 XPC_WN_Helper_NewResolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
                          JSObject **objp)
 {
     nsresult rv = NS_OK;
     JSBool retval = JS_TRUE;
--- a/js/src/yarr/YarrJIT.cpp
+++ b/js/src/yarr/YarrJIT.cpp
@@ -77,20 +77,27 @@ class YarrGenerator : private MacroAssem
     static const RegisterID length = X86Registers::ecx;
     static const RegisterID output = X86Registers::edi;
 
     static const RegisterID regT0 = X86Registers::ebx;
     static const RegisterID regT1 = X86Registers::esi;
 
     static const RegisterID returnRegister = X86Registers::eax;
 #elif WTF_CPU_X86_64
+#if WTF_PLATFORM_WIN
+    static const RegisterID input = X86Registers::ecx;
+    static const RegisterID index = X86Registers::edx;
+    static const RegisterID length = X86Registers::r8;
+    static const RegisterID output = X86Registers::r9;
+#else
     static const RegisterID input = X86Registers::edi;
     static const RegisterID index = X86Registers::esi;
     static const RegisterID length = X86Registers::edx;
     static const RegisterID output = X86Registers::ecx;
+#endif
 
     static const RegisterID regT0 = X86Registers::eax;
     static const RegisterID regT1 = X86Registers::ebx;
 
     static const RegisterID returnRegister = X86Registers::eax;
 #endif
 
     void optimizeAlternative(PatternAlternative* alternative)
--- a/mobile/build.mk
+++ b/mobile/build.mk
@@ -63,17 +63,16 @@ tier_app_dirs += \
   mobile \
   $(NULL)
 
 
 installer: 
 	@$(MAKE) -C mobile/installer installer
 
 package:
-	rm -rf dist/fennec*
 	@$(MAKE) -C mobile/installer
 
 install::
 	@echo "Mobile can't be installed directly."
 	@exit 1
 
 deb: package
 	@$(MAKE) -C mobile/installer deb