Blob Blame History Raw

# HG changeset patch
# User Cameron Kaiser <spectre@floodgap.com>
# Date 1612231460 0
# Node ID 579a66fd796690fb752485215b2edaa6167ebf16
# Parent  a00504e040bfd34d01c74d478beb9d308ec085be
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

diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_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++;
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp
--- 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++;