blob: fb672d39a5978f5abcb36f3e56a49c5b412d14bf (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
# 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++;
|