[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#824449: firefox: FTBFS on sparc64 due to wrong platform definitions



Attaching my latest patch which makes use of the ARM64 memory allocator, both for the
Javascript engine as well as mozjemalloc. It seems to fix the memory corruption and
allocation issues, but Firefox now crashes with SIGBUS in the xulrunner stub (see
below).

If anyone wants to have a go at this, just get the source of the current firefox
package in Debian (version 50) and apply the patch with "patch -p1", then run
"dpkg-source --commit" in the source tree to apply the patch to quilt.

Thanks,
Adrian

Thread 1 "xpcshell" received signal SIGBUS, Bus error.
0xfff8000100c12224 in invoke_copy_to_stack (d=<optimized out>, paramCount=<optimized out>, s=<optimized out>)
    at /build/firefox-wic4ZJ/firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp:126
126                 break;
(gdb)  bt
#0  0xfff8000100c12224 in invoke_copy_to_stack (d=<optimized out>, paramCount=<optimized out>, s=<optimized out>)
    at /build/firefox-wic4ZJ/firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp:126
#1  0xfff8000100c1760c in NS_InvokeByIndex ()
    at /build/firefox-wic4ZJ/firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s:32
#2  0xfff800010116084c in CallMethodHelper::Invoke (this=0x7feffffc6a8)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/xpconnect/src/XPCWrappedNative.cpp:2075
#3  CallMethodHelper::Call (this=0x7feffffc6a8)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/xpconnect/src/XPCWrappedNative.cpp:1394
#4  XPCWrappedNative::CallMethod (ccx=..., mode=mode@entry=XPCWrappedNative::CALL_GETTER)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/xpconnect/src/XPCWrappedNative.cpp:1361
#5  0xfff8000101167560 in XPCWrappedNative::GetAttribute (ccx=...)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/xpconnect/src/xpcprivate.h:1950
#6  XPC_WN_GetterSetter (cx=<optimized out>, cx@entry=0x7000189a000, argc=<optimized out>, vp=0x7feffffcc28)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/xpconnect/src/XPCWrappedNativeJSOps.cpp:1164
#7  0xfff8000102bacc5c in js::CallJSNative (args=..., native=<optimized out>, cx=0x7000189a000)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/jscntxtinlines.h:235
#8  js::InternalCallOrConstruct (cx=0x7000189a000, args=..., construct=<optimized out>)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/Interpreter.cpp:453
#9  0xfff8000102bacde0 in InternalCall (cx=cx@entry=0x7000189a000, args=...)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/Interpreter.cpp:498
#10 0xfff8000102bace50 in js::Call (cx=cx@entry=0x7000189a000, fval=..., thisv=..., args=..., rval=...)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/Interpreter.cpp:517
#11 0xfff8000102bacf08 in js::CallGetter (cx=cx@entry=0x7000189a000, thisv=..., getter=..., rval=...)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/Interpreter.cpp:631
#12 0xfff8000102bacfe0 in CallGetter (cx=cx@entry=0x7000189a000, obj=..., receiver=..., shape=..., vp=...)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/NativeObject.cpp:1737
#13 0xfff8000102bad264 in GetExistingProperty<(js::AllowGC)1> (vp=..., shape=..., obj=..., receiver=..., cx=0x7000189a000)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/NativeObject.cpp:1785
#14 NativeGetPropertyInline<(js::AllowGC)1> (vp=..., nameLookup=NotNameLookup, id=..., receiver=..., obj=...,
---Type <return> to continue, or q <return> to quit---
    0) at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/NativeObject.cpp:2012

#15 js::NativeGetProperty (cx=0x7000189a000, obj=..., receiver=..., id=..., vp=...) at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/NativeObject.cpp:2046

#16 0xfff8000102a264b0 in js::GetProperty (cx=cx@entry=0x7000189a000, obj=..., receiver=..., id=..., vp=...) at
/build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/NativeObject.h:1478
#17 0xfff8000102bae7f0 in js::GetProperty (vp=..., name=<optimized out>, receiver=..., obj=..., cx=0x7000189a000) at
/build/firefox-wic4ZJ/firefox-50.0.2/js/src/jsobj.h:836
#18 js::GetProperty (cx=0x7000189a000, v=..., name=..., vp=...) at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/Interpreter.cpp:4161

#19 0xfff8000102ba1bb4 in GetPropertyOperation (vp=..., lval=..., pc=<optimized out>, script=..., fp=<optimized out>, cx=<optimized out>)

    at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/Interpreter.cpp:189

#20 Interpret (cx=0x7000189a000, state=...) at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/Interpreter.cpp:2590

#21 0xfff8000102bac9a4 in js::RunScript (cx=cx@entry=0x7000189a000, state=...) at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/Interpreter.cpp:399

#22 0xfff8000102bb55a4 in js::ExecuteKernel (cx=cx@entry=0x7000189a000, script=..., scopeChainArg=..., newTargetValue=..., evalInFrame=...,
result=result@entry=0x7feffffd990)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/Interpreter.cpp:679

#23 0xfff8000102bb56ec in js::Execute (cx=cx@entry=0x7000189a000, script=..., scopeChainArg=..., rval=rval@entry=0x7feffffd990)

    at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/vm/Interpreter.cpp:712

#24 0xfff8000102a25a9c in ExecuteScript (cx=cx@entry=0x7000189a000, scope=..., script=..., rval=rval@entry=0x7feffffd990) at
/build/firefox-wic4ZJ/firefox-50.0.2/js/src/jsapi.cpp:4343
#25 0xfff8000102a2cccc in JS_ExecuteScript (cx=0x7000189a000, scriptArg=..., rval=...) at /build/firefox-wic4ZJ/firefox-50.0.2/js/src/jsapi.cpp:4369

#26 0xfff8000101148d9c in ProcessFile (jsapi=..., filename=filename@entry=0x7fefffff720
"/build/firefox-wic4ZJ/firefox-50.0.2/toolkit/mozapps/installer/precompile_cache.js",
    file=file@entry=0x700040e7800, forceTTY=forceTTY@entry=false) at /build/firefox-wic4ZJ/firefox-50.0.2/js/xpconnect/src/XPCShellImpl.cpp:875

#27 0xfff8000100b6deb0 in Process (jsapi=..., filename=0x7fefffff720 "/build/firefox-wic4ZJ/firefox-50.0.2/toolkit/mozapps/installer/precompile_cache.js",
forceTTY=<optimized out>)
    at /build/firefox-wic4ZJ/firefox-50.0.2/js/xpconnect/src/XPCShellImpl.cpp:928

#28 0xfff800010114e4ac in ProcessArgs (aDirProvider=0x7feffffed18, argc=4, argv=0x7fefffff440, jsapi=...) at
/build/firefox-wic4ZJ/firefox-50.0.2/js/xpconnect/src/XPCShellImpl.cpp:1075
#29 XRE_XPCShellMain (argc=4, argv=0x7fefffff440, envp=<optimized out>, aShellData=<optimized out>) at
/build/firefox-wic4ZJ/firefox-50.0.2/js/xpconnect/src/XPCShellImpl.cpp:1570
#30 0x0000010000003f3c in main (argc=<optimized out>, argv=<optimized out>, envp=0x7fefffff468) at
/build/firefox-wic4ZJ/firefox-50.0.2/js/xpconnect/shell/xpcshell.cpp:62
(gdb)


> [1] https://hg.mozilla.org/mozilla-central/rev/dfaafbaaa291

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913
Description: Fix build on sparc64
 - use proper pre-preprocessor definitions (not __sparc64__)
 - use arm64 allocator in mozjemalloc and JavaScript Memory.cpp
 - provide xulstubs for Linux/sparc64 (based on an old patch for FF17)
 .
Index: firefox-50.0.2/ipc/chromium/src/build/build_config.h
===================================================================
--- firefox-50.0.2.orig/ipc/chromium/src/build/build_config.h
+++ firefox-50.0.2/ipc/chromium/src/build/build_config.h
@@ -83,7 +83,7 @@
 #elif defined(__ppc__) || defined(__powerpc__)
 #define ARCH_CPU_PPC 1
 #define ARCH_CPU_32_BITS 1
-#elif defined(__sparc64__)
+#elif defined(__sparc__) && defined(__arch64__)
 #define ARCH_CPU_SPARC 1
 #define ARCH_CPU_64_BITS 1
 #elif defined(__sparc__)
Index: firefox-50.0.2/js/src/gc/Memory.cpp
===================================================================
--- firefox-50.0.2.orig/js/src/gc/Memory.cpp
+++ firefox-50.0.2/js/src/gc/Memory.cpp
@@ -490,7 +490,7 @@ static inline void*
 MapMemoryAt(void* desired, size_t length, int prot = PROT_READ | PROT_WRITE,
             int flags = MAP_PRIVATE | MAP_ANON, int fd = -1, off_t offset = 0)
 {
-#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__)) || defined(__aarch64__)
+#if defined(__ia64__) || (defined(__sparc__) && defined(__arch64__)) || defined(__aarch64__)
     MOZ_ASSERT((0xffff800000000000ULL & (uintptr_t(desired) + length - 1)) == 0);
 #endif
     void* region = mmap(desired, length, prot, flags, fd, offset);
@@ -513,7 +513,7 @@ static inline void*
 MapMemory(size_t length, int prot = PROT_READ | PROT_WRITE,
           int flags = MAP_PRIVATE | MAP_ANON, int fd = -1, off_t offset = 0)
 {
-#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__))
+#if defined(__ia64__) || (defined(__sparc__) && defined(__arch64__) && defined(__NetBSD__))
     /*
      * The JS engine assumes that all allocated pointers have their high 17 bits clear,
      * which ia64's mmap doesn't support directly. However, we can emulate it by passing
@@ -540,7 +540,7 @@ MapMemory(size_t length, int prot = PROT
         return nullptr;
     }
     return region;
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) || (defined(__sparc__) && defined(__arch64__))
    /*
     * There might be similar virtual address issue on arm64 which depends on
     * hardware and kernel configurations. But the work around is slightly
Index: firefox-50.0.2/js/src/jsapi-tests/testGCAllocator.cpp
===================================================================
--- firefox-50.0.2.orig/js/src/jsapi-tests/testGCAllocator.cpp
+++ firefox-50.0.2/js/src/jsapi-tests/testGCAllocator.cpp
@@ -312,7 +312,7 @@ void unmapPages(void* p, size_t size) {
 void*
 mapMemoryAt(void* desired, size_t length)
 {
-#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__)) || defined(__aarch64__)
+#if defined(__ia64__) || (defined(__sparc__) && defined(__arch64__)) || defined(__aarch64__)
     MOZ_RELEASE_ASSERT(0xffff800000000000ULL & (uintptr_t(desired) + length - 1) == 0);
 #endif
     void* region = mmap(desired, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
@@ -334,7 +334,7 @@ mapMemory(size_t length)
     int fd = -1;
     off_t offset = 0;
     // The test code must be aligned with the implementation in gc/Memory.cpp.
-#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__))
+#if defined(__ia64__) || (defined(__sparc__) && defined(__arch64__) && defined(__NetBSD__))
     void* region = mmap((void*)0x0000070000000000, length, prot, flags, fd, offset);
     if (region == MAP_FAILED)
         return nullptr;
@@ -344,7 +344,7 @@ mapMemory(size_t length)
         return nullptr;
     }
     return region;
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) || (defined(__sparc__) && defined(__arch64__))
     const uintptr_t start = UINT64_C(0x0000070000000000);
     const uintptr_t end   = UINT64_C(0x0000800000000000);
     const uintptr_t step  = js::gc::ChunkSize;
Index: firefox-50.0.2/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h
===================================================================
--- firefox-50.0.2.orig/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h
+++ firefox-50.0.2/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h
@@ -67,7 +67,7 @@
 #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
 #elif defined(sparc)
 #define GOOGLE_PROTOBUF_ARCH_SPARC 1
-#ifdef SOLARIS_64BIT_ENABLED
+#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
 #define GOOGLE_PROTOBUF_ARCH_64_BIT 1
 #else
 #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
Index: firefox-50.0.2/memory/mozjemalloc/jemalloc.c
===================================================================
--- firefox-50.0.2.orig/memory/mozjemalloc/jemalloc.c
+++ firefox-50.0.2/memory/mozjemalloc/jemalloc.c
@@ -485,7 +485,7 @@ static const bool isthreaded = true;
 #  define SIZEOF_PTR_2POW	3
 #  define NO_TLS
 #endif
-#ifdef __sparc64__
+#if defined(__sparc__) && defined(__arch64__)
 #  define QUANTUM_2POW_MIN	4
 #  define SIZEOF_PTR_2POW	3
 #  define NO_TLS
@@ -2412,7 +2412,7 @@ static void *
 pages_map(void *addr, size_t size)
 {
 	void *ret;
-#if defined(__ia64__)
+#if defined(__ia64__) || (defined(__sparc__) && defined(__arch64__))
         /*
          * The JS engine assumes that all allocated pointers have their high 17 bits clear,
          * which ia64's mmap doesn't support directly. However, we can emulate it by passing
@@ -2444,7 +2444,7 @@ pages_map(void *addr, size_t size)
 	if (ret == MAP_FAILED) {
 		ret = NULL;
 	}
-#if defined(__ia64__)
+#if defined(__ia64__) || (defined(__sparc__) && defined(__arch64__))
         /* 
          * If the allocated memory doesn't have its upper 17 bits clear, consider it 
          * as out of memory.
@@ -2477,7 +2477,7 @@ pages_map(void *addr, size_t size)
 		MozTagAnonymousMemory(ret, size, "jemalloc");
 	}
 
-#if defined(__ia64__)
+#if defined(__ia64__) || (defined(__sparc__) && defined(__arch64__))
 	assert(ret == NULL || (!check_placement && ret != NULL)
 	    || (check_placement && ret == addr));
 #else
Index: firefox-50.0.2/memory/jemalloc/src/include/jemalloc/internal/mb.h
===================================================================
--- firefox-50.0.2.orig/memory/jemalloc/src/include/jemalloc/internal/mb.h
+++ firefox-50.0.2/memory/jemalloc/src/include/jemalloc/internal/mb.h
@@ -76,7 +76,7 @@ mb_write(void)
 	    : "memory" /* Clobbers. */
 	    );
 }
-#elif defined(__sparc64__)
+#elif defined(__sparc__) && defined(__arch64__)
 JEMALLOC_INLINE void
 mb_write(void)
 {
Index: firefox-50.0.2/media/webrtc/trunk/build/build_config.h
===================================================================
--- firefox-50.0.2.orig/media/webrtc/trunk/build/build_config.h
+++ firefox-50.0.2/media/webrtc/trunk/build/build_config.h
@@ -129,7 +129,7 @@
 #define ARCH_CPU_PPC 1
 #define ARCH_CPU_32_BITS 1
 #define ARCH_CPU_BIG_ENDIAN 1
-#elif defined(__sparc64__)
+#elif defined(__sparc__) && defined(__arch64__)
 #define ARCH_CPU_SPARC_FAMILY 1
 #define ARCH_CPU_SPARC 1
 #define ARCH_CPU_64_BITS 1
Index: firefox-50.0.2/widget/gonk/libui/sha1.c
===================================================================
--- firefox-50.0.2.orig/widget/gonk/libui/sha1.c
+++ firefox-50.0.2/widget/gonk/libui/sha1.c
@@ -87,7 +87,7 @@ typedef union {
 
 /* old sparc64 gcc could not compile this */
 #undef SPARC64_GCC_WORKAROUND
-#if defined(__sparc64__) && defined(__GNUC__) && __GNUC__ < 3
+#if defined(__sparc__) && defined(__arch64__) && defined(__GNUC__) && __GNUC__ < 3
 #define SPARC64_GCC_WORKAROUND
 #endif
 
Index: firefox-50.0.2/media/webrtc/trunk/webrtc/typedefs.h
===================================================================
--- firefox-50.0.2.orig/media/webrtc/trunk/webrtc/typedefs.h
+++ firefox-50.0.2/media/webrtc/trunk/webrtc/typedefs.h
@@ -61,7 +61,7 @@
 #define WEBRTC_ARCH_BIG_ENDIAN
 #define WEBRTC_BIG_ENDIAN
 #endif
-#elif defined(__sparc64__)
+#elif defined(__sparc__) && defined(__arch64__)
 #define WEBRTC_ARCH_SPARC 1
 #define WEBRTC_ARCH_64_BITS 1
 #define WEBRTC_ARCH_BIG_ENDIAN
Index: firefox-50.0.2/js/src/jsscript.h
===================================================================
--- firefox-50.0.2.orig/js/src/jsscript.h
+++ firefox-50.0.2/js/src/jsscript.h
@@ -94,6 +94,10 @@ enum JSTryNoteKind {
 struct JSTryNote {
     uint8_t         kind;       /* one of JSTryNoteKind */
     uint32_t        stackDepth; /* stack depth upon exception handler entry */
+#if defined(__sparc__)
+    uint8_t         pad1;
+    uint16_t        pad2;
+#endif
     uint32_t        start;      /* start of the try statement or loop
                                    relative to script->main */
     uint32_t        length;     /* length of the try statement or loop */
Index: firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_linux.s
===================================================================
--- /dev/null
+++ firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_linux.s
@@ -0,0 +1,86 @@
+/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+    Platform specific code to invoke XPCOM methods on native objects
+    for sparcv9 GNU/Linux.
+
+    See the SPARC Compliance Definition (SCD) Chapter 3
+    for more information about what is going on here, including
+    the use of BIAS (0x7ff).
+    The SCD is available from http://www.sparc.com/.
+*/
+
+        .global NS_InvokeByIndex_P
+        .type   NS_InvokeByIndex_P, #function
+
+/*
+    NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+                     uint32_t paramCount, nsXPTCVariant* params);
+    
+*/
+NS_InvokeByIndex_P:
+        save    %sp,-(128 + 64),%sp ! room for the register window and
+                                    ! struct pointer, rounded up to 0 % 64
+        sll     %i2,4,%l0           ! assume the worst case
+                                    ! paramCount * 2 * 8 bytes
+        cmp     %l0, 0              ! are there any args? If not,
+        be      .invoke             ! no need to copy args to stack
+        nop
+
+        sub     %sp,%l0,%sp         ! create the additional stack space
+        add     %sp,0x7ff+136,%o0   ! step past the register window, the
+                                    ! struct result pointer and the 'this' slot
+        mov     %i2,%o1             ! paramCount
+        call    invoke_copy_to_stack
+        mov     %i3,%o2             ! params
+
+!
+!   load arguments from stack into the outgoing registers
+!   BIAS is 0x7ff (2047)
+!
+
+!   load the %o1..5 64bit (extended word) output registers registers 
+        ldx     [%sp + 0x7ff + 136],%o1    ! %i1
+        ldx     [%sp + 0x7ff + 144],%o2    ! %i2
+        ldx     [%sp + 0x7ff + 152],%o3    ! %i3
+        ldx     [%sp + 0x7ff + 160],%o4    ! %i4
+        ldx     [%sp + 0x7ff + 168],%o5    ! %i5
+
+!   load the even number double registers starting with %f2
+        ldd     [%sp + 0x7ff + 136],%f2
+        ldd     [%sp + 0x7ff + 144],%f4
+        ldd     [%sp + 0x7ff + 152],%f6
+        ldd     [%sp + 0x7ff + 160],%f8
+        ldd     [%sp + 0x7ff + 168],%f10
+        ldd     [%sp + 0x7ff + 176],%f12
+        ldd     [%sp + 0x7ff + 184],%f14
+        ldd     [%sp + 0x7ff + 192],%f16
+        ldd     [%sp + 0x7ff + 200],%f18
+        ldd     [%sp + 0x7ff + 208],%f20
+        ldd     [%sp + 0x7ff + 216],%f22
+        ldd     [%sp + 0x7ff + 224],%f24
+        ldd     [%sp + 0x7ff + 232],%f26
+        ldd     [%sp + 0x7ff + 240],%f28
+        ldd     [%sp + 0x7ff + 248],%f30
+
+!
+!   calculate the target address from the vtable
+!
+.invoke:
+        sll     %i1,3,%l0           ! index *= 8
+!       add     %l0,16,%l0          ! there are 2 extra entries in the vTable (16bytes)
+        ldx     [%i0],%l1           ! *that --> address of vtable
+        ldx     [%l0 + %l1],%l0     ! that->vtable[index * 8 + 16] --> address
+
+        jmpl    %l0,%o7             ! call the routine
+        mov     %i0,%o0             ! move 'this' pointer to out register
+
+        mov     %o0,%i0             ! propagate return value
+        ret
+        restore
+
+        .size    NS_InvokeByIndex_P, .-NS_InvokeByIndex_P
Index: firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_linux.cpp
===================================================================
--- /dev/null
+++ firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_linux.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+extern "C" uint64_t
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+  /*
+    We need to copy the parameters for this function to locals and use them
+    from there since the parameters occupy the same stack space as the stack
+    we're trying to populate.
+  */
+  uint64_t *l_d = d;
+  nsXPTCVariant *l_s = s;
+  uint64_t l_paramCount = paramCount;
+  uint64_t regCount = 0;  // return the number of registers to load from the stack
+
+  for(uint64_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+  {
+    if (regCount < 5) regCount++;
+
+    if (l_s->IsPtrData())
+    {
+      *l_d = (uint64_t)l_s->ptr;
+      continue;
+    }
+    switch (l_s->type)
+    {
+      case nsXPTType::T_I8    : *((int64_t*)l_d)     = l_s->val.i8;    break;
+      case nsXPTType::T_I16   : *((int64_t*)l_d)     = l_s->val.i16;   break;
+      case nsXPTType::T_I32   : *((int64_t*)l_d)     = l_s->val.i32;   break;
+      case nsXPTType::T_I64   : *((int64_t*)l_d)     = l_s->val.i64;   break;
+      
+      case nsXPTType::T_U8    : *((uint64_t*)l_d)    = l_s->val.u8;    break;
+      case nsXPTType::T_U16   : *((uint64_t*)l_d)    = l_s->val.u16;   break;
+      case nsXPTType::T_U32   : *((uint64_t*)l_d)    = l_s->val.u32;   break;
+      case nsXPTType::T_U64   : *((uint64_t*)l_d)    = l_s->val.u64;   break;
+
+      /* in the case of floats, we want to put the bits in to the
+         64bit space right justified... floats in the parameter array on
+         sparcv9 use odd numbered registers.. %f1, %f3, so we have to skip
+         the space that would be occupied by %f0, %f2, etc.
+      */
+      case nsXPTType::T_FLOAT : *(((float*)l_d) + 1) = l_s->val.f;     break;
+      case nsXPTType::T_DOUBLE: *((double*)l_d)      = l_s->val.d;     break;
+      case nsXPTType::T_BOOL  : *((int64_t*)l_d)     = l_s->val.b;     break;
+      case nsXPTType::T_CHAR  : *((uint64_t*)l_d)    = l_s->val.c;     break;
+      case nsXPTType::T_WCHAR : *((int64_t*)l_d)     = l_s->val.wc;    break;
+
+      default:
+        // all the others are plain pointer types
+        *((void**)l_d) = l_s->val.p;
+        break;
+    }
+  }
+  
+  return regCount;
+}
Index: firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_linux.s
===================================================================
--- /dev/null
+++ firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_linux.s
@@ -0,0 +1,50 @@
+/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+        .global SharedStub
+
+/*
+    in the frame for the function that called SharedStub are the
+    rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+        mov     %o0, %o1               ! shuffle the index up to 2nd place
+        mov     %i0, %o0               ! the original 'this'
+        add     %fp, 0x7ff + 136, %o2  ! previous stack top adjusted to the first argument slot (beyond 'this')
+
+! save off the original incoming parameters that arrived in 
+! registers, the ABI guarantees the space for us to do this
+        stx     %i1, [%fp + 0x7ff + 136]
+        stx     %i2, [%fp + 0x7ff + 144]
+        stx     %i3, [%fp + 0x7ff + 152]
+        stx     %i4, [%fp + 0x7ff + 160]
+        stx     %i5, [%fp + 0x7ff + 168]
+! now we can build our own stack frame
+        save    %sp,-(128 + 64),%sp    ! room for the register window and
+                                       ! struct pointer, rounded up to 0 % 64
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args)
+! so we can just copy these through
+
+        mov     %i0, %o0
+        mov     %i1, %o1
+        mov     %i2, %o2
+        call    PrepareAndDispatch
+        nop
+        mov     %o0,%i0             ! propagate return value
+        b .LL1
+        nop
+.LL1:
+        ret
+        restore
+
+       .size    SharedStub, .-SharedStub
+       .type    SharedStub, #function
Index: firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_linux.cpp
===================================================================
--- /dev/null
+++ firefox-50.0.2/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_linux.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args)
+{
+
+#define PARAM_BUFFER_COUNT     16
+
+    nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+    nsXPTCMiniVariant* dispatchParams = NULL;
+    const nsXPTMethodInfo* info;
+    uint8_t paramCount;
+    uint8_t i;
+    nsresult result = NS_ERROR_FAILURE;
+
+    NS_ASSERTION(self,"no self");
+
+    self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+    NS_ASSERTION(info,"no interface info");
+
+    paramCount = info->GetParamCount();
+
+    // setup variant array pointer
+    if(paramCount > PARAM_BUFFER_COUNT)
+        dispatchParams = new nsXPTCMiniVariant[paramCount];
+    else
+        dispatchParams = paramBuffer;
+
+    NS_ASSERTION(dispatchParams,"no place for params");
+    if (!dispatchParams)
+        return NS_ERROR_OUT_OF_MEMORY;
+
+    uint64_t* ap = args;
+    for(i = 0; i < paramCount; i++, ap++)
+    {
+        const nsXPTParamInfo& param = info->GetParam(i);
+        const nsXPTType& type = param.GetType();
+        nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+        if(param.IsOut() || !type.IsArithmetic())
+        {
+            dp->val.p = (void*) *ap;
+            continue;
+        }
+        // else
+        switch(type)
+        {
+        case nsXPTType::T_BOOL   : dp->val.b   = *((int64_t*)  ap);      break;
+        case nsXPTType::T_CHAR   : dp->val.c   = *((uint64_t*) ap);      break;
+        case nsXPTType::T_WCHAR  : dp->val.wc  = *((int64_t*) ap);       break;
+        case nsXPTType::T_I8     : dp->val.i8  = *((int64_t*)  ap);      break;
+        case nsXPTType::T_I16    : dp->val.i16 = *((int64_t*) ap);       break;
+        case nsXPTType::T_I32    : dp->val.i32 = *((int64_t*) ap);       break;
+        case nsXPTType::T_I64    : dp->val.i64 = *((int64_t*) ap);       break;
+        case nsXPTType::T_U8     : dp->val.u8  = *((uint64_t*) ap);      break;
+        case nsXPTType::T_U16    : dp->val.u16 = *((uint64_t*)ap);       break;
+        case nsXPTType::T_U32    : dp->val.u32 = *((uint64_t*)ap);       break;
+        case nsXPTType::T_U64    : dp->val.u64 = *((uint64_t*) ap);      break;
+        case nsXPTType::T_FLOAT  : dp->val.f   = ((float*)   ap)[1];     break;
+        case nsXPTType::T_DOUBLE : dp->val.d   = *((double*) ap);        break;
+        default:
+            NS_ERROR("bad type");
+            break;
+        }
+    }
+
+    result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+    if(dispatchParams != paramBuffer)
+        delete [] dispatchParams;
+
+    return result;
+}
+
+extern "C" int SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+	int dummy; /* defeat tail-call optimization */ \
+	return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+    NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+    return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
Index: firefox-50.0.2/memory/mozjemalloc/jemalloc.c
===================================================================
--- firefox-50.0.2.orig/memory/mozjemalloc/jemalloc.c
+++ firefox-50.0.2/memory/mozjemalloc/jemalloc.c
@@ -2432,7 +2432,34 @@ pages_map(void *addr, size_t size)
 		check_placement = false;
 	}
 #endif
-
+#if defined(__sparc__) && defined(__arch64__)
+    const uintptr_t start = UINT64_C(0x0000070000000000);
+    const uintptr_t end   = UINT64_C(0x0000800000000000);
+    const uintptr_t step  = 8 << 20;
+   /*
+    * Optimization options if there are too many retries in practice:
+    * 1. Examine /proc/self/maps to find an available address. This file is
+    *    not always available, however. In addition, even if we examine
+    *    /proc/self/maps, we may still need to retry several times due to
+    *    racing with other threads.
+    * 2. Use a global/static variable with lock to track the addresses we have
+    *    allocated or tried.
+    */
+    uintptr_t hint;
+    void* region = MAP_FAILED;
+    for (hint = start; region == MAP_FAILED && hint + size <= end; hint += step) {
+	    region = mmap((void*)hint, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+	    if (region != MAP_FAILED) {
+		    if (((size_t) region + (size - 1)) & 0xffff800000000000) {
+			    if (munmap(region, size)) {
+				    MOZ_ASSERT(errno == ENOMEM);
+			    }
+			    region = MAP_FAILED;
+		    }
+	    }
+    }
+    ret = region;
+#else
 	/*
 	 * We don't use MAP_FIXED here, because it can cause the *replacement*
 	 * of existing mappings, and we only want to create new mappings.
@@ -2440,7 +2467,7 @@ pages_map(void *addr, size_t size)
 	ret = mmap(addr, size, PROT_READ | PROT_WRITE,
 		MAP_PRIVATE | MAP_ANON, -1, 0);
 	assert(ret != NULL);
-
+#endif
 	if (ret == MAP_FAILED) {
 		ret = NULL;
 	}

Reply to: