# HG changeset patch # User Cameron Kaiser # 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++;