Bug 1690152 - on ppc64 properly skip parameter slots if we overflow GPRs while still having FPRs to burn. r=tcampbell
authorCameron Kaiser <spectre@floodgap.com>
Tue, 02 Feb 2021 02:04:20 +0000
changeset 565544 579a66fd796690fb752485215b2edaa6167ebf16
parent 565543 a00504e040bfd34d01c74d478beb9d308ec085be
child 565545 4b90835c5e07cdff39fee6a9bf8da55170cc394a
push id38162
push usernerli@mozilla.com
push dateTue, 02 Feb 2021 09:51:07 +0000
treeherdermozilla-central@57bcdf857d44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1690152
milestone87.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1690152 - on ppc64 properly skip parameter slots if we overflow GPRs while still having FPRs to burn. r=tcampbell Differential Revision: https://phabricator.services.mozilla.com/D103724
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp
xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp
--- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp
@@ -86,27 +86,37 @@ extern "C" void invoke_copy_to_stack(uin
             case nsXPTType::T_WCHAR:  value = s->val.wc;            break;
             default:                  value = (uint64_t) s->val.p;  break;
             }
         }
 
         if (!s->IsIndirect() && s->type == nsXPTType::T_DOUBLE) {
             if (nr_fpr < FPR_COUNT) {
                 fpregs[nr_fpr++] = s->val.d;
-                nr_gpr++;
+                // Even if we have enough FPRs, still skip space in
+                // the parameter area if we ran out of placeholder GPRs.
+                if (nr_gpr < GPR_COUNT) {
+                    nr_gpr++;
+                } else {
+                    d++;
+                }
             } else {
                 *((double *)d) = s->val.d;
                 d++;
             }
         }
         else if (!s->IsIndirect() && s->type == nsXPTType::T_FLOAT) {
             if (nr_fpr < FPR_COUNT) {
                 // Single-precision floats are passed in FPRs too.
                 fpregs[nr_fpr++] = s->val.f;
-                nr_gpr++;
+                if (nr_gpr < GPR_COUNT) {
+                    nr_gpr++;
+                } else {
+                    d++;
+                }
             } else {
 #ifdef __LITTLE_ENDIAN__
                 *((float *)d) = s->val.f;
 #else
                 // Big endian needs adjustment to point to the least
                 // significant word.
                 float* p = (float*)d;
                 p++;
--- a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp
@@ -98,27 +98,37 @@ PrepareAndDispatch(nsXPTCStubBase * self
                 nr_gpr++;
             else
                 ap++;
         }
 
         if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
             if (nr_fpr < FPR_COUNT) {
                 dp->val.d = fpregs[nr_fpr++];
-                nr_gpr++;
+                // Even if we have enough FPRs, still skip space in
+                // the parameter area if we ran out of placeholder GPRs.
+                if (nr_gpr < GPR_COUNT) {
+                    nr_gpr++;
+                } else {
+                    ap++;
+                }
             } else {
                 dp->val.d = *(double*)ap++;
             }
             continue;
         }
         if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
             if (nr_fpr < FPR_COUNT) {
                 // Single-precision floats are passed in FPRs too.
                 dp->val.f = (float)fpregs[nr_fpr++];
-                nr_gpr++;
+                if (nr_gpr < GPR_COUNT) {
+                    nr_gpr++;
+                } else {
+                    ap++;
+                }
             } else {
 #ifdef __LITTLE_ENDIAN__
                 dp->val.f = *(float*)ap++;
 #else
                 // Big endian needs adjustment to point to the least
                 // significant word.
                 float* p = (float*)ap;
                 p++;