|
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 /* Platform specific code to invoke XPCOM methods on native objects */ |
|
8 |
|
9 #include "xptcprivate.h" |
|
10 |
|
11 |
|
12 static uint32_t |
|
13 invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) |
|
14 { |
|
15 uint32_t overflow = 0, gpr = 1 /*this*/, fpr = 0; |
|
16 for(uint32_t i = 0; i < paramCount; i++, s++) |
|
17 { |
|
18 if(s->IsPtrData()) |
|
19 { |
|
20 if (gpr < 5) gpr++; else overflow++; |
|
21 continue; |
|
22 } |
|
23 switch(s->type) |
|
24 { |
|
25 case nsXPTType::T_I8 : |
|
26 case nsXPTType::T_I16 : |
|
27 case nsXPTType::T_I32 : |
|
28 case nsXPTType::T_I64 : |
|
29 if (gpr < 5) gpr++; else overflow++; |
|
30 break; |
|
31 case nsXPTType::T_U8 : |
|
32 case nsXPTType::T_U16 : |
|
33 case nsXPTType::T_U32 : |
|
34 case nsXPTType::T_U64 : |
|
35 if (gpr < 5) gpr++; else overflow++; |
|
36 break; |
|
37 case nsXPTType::T_FLOAT : |
|
38 case nsXPTType::T_DOUBLE : |
|
39 if (fpr < 4) fpr++; else overflow++; |
|
40 break; |
|
41 case nsXPTType::T_BOOL : |
|
42 case nsXPTType::T_CHAR : |
|
43 case nsXPTType::T_WCHAR : |
|
44 if (gpr < 5) gpr++; else overflow++; |
|
45 break; |
|
46 default: |
|
47 // all the others are plain pointer types |
|
48 if (gpr < 5) gpr++; else overflow++; |
|
49 break; |
|
50 } |
|
51 } |
|
52 /* Round up number of overflow words to ensure stack |
|
53 stays aligned to 8 bytes. */ |
|
54 return (overflow + 1) & ~1; |
|
55 } |
|
56 |
|
57 static void |
|
58 invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint64_t* d_ov, uint32_t overflow) |
|
59 { |
|
60 uint64_t *d_gpr = d_ov + overflow; |
|
61 uint64_t *d_fpr = (uint64_t *)(d_gpr + 4); |
|
62 uint32_t gpr = 1 /*this*/, fpr = 0; |
|
63 |
|
64 for(uint32_t i = 0; i < paramCount; i++, s++) |
|
65 { |
|
66 if(s->IsPtrData()) |
|
67 { |
|
68 if (gpr < 5) |
|
69 *((void**)d_gpr) = s->ptr, d_gpr++, gpr++; |
|
70 else |
|
71 *((void**)d_ov ) = s->ptr, d_ov++; |
|
72 continue; |
|
73 } |
|
74 switch(s->type) |
|
75 { |
|
76 case nsXPTType::T_I8 : |
|
77 if (gpr < 5) |
|
78 *((int64_t*) d_gpr) = s->val.i8, d_gpr++, gpr++; |
|
79 else |
|
80 *((int64_t*) d_ov ) = s->val.i8, d_ov++; |
|
81 break; |
|
82 case nsXPTType::T_I16 : |
|
83 if (gpr < 5) |
|
84 *((int64_t*) d_gpr) = s->val.i16, d_gpr++, gpr++; |
|
85 else |
|
86 *((int64_t*) d_ov ) = s->val.i16, d_ov++; |
|
87 break; |
|
88 case nsXPTType::T_I32 : |
|
89 if (gpr < 5) |
|
90 *((int64_t*) d_gpr) = s->val.i32, d_gpr++, gpr++; |
|
91 else |
|
92 *((int64_t*) d_ov ) = s->val.i32, d_ov++; |
|
93 break; |
|
94 case nsXPTType::T_I64 : |
|
95 if (gpr < 5) |
|
96 *((int64_t*) d_gpr) = s->val.i64, d_gpr++, gpr++; |
|
97 else |
|
98 *((int64_t*) d_ov ) = s->val.i64, d_ov++; |
|
99 break; |
|
100 case nsXPTType::T_U8 : |
|
101 if (gpr < 5) |
|
102 *((uint64_t*) d_gpr) = s->val.u8, d_gpr++, gpr++; |
|
103 else |
|
104 *((uint64_t*) d_ov ) = s->val.u8, d_ov++; |
|
105 break; |
|
106 case nsXPTType::T_U16 : |
|
107 if (gpr < 5) |
|
108 *((uint64_t*)d_gpr) = s->val.u16, d_gpr++, gpr++; |
|
109 else |
|
110 *((uint64_t*)d_ov ) = s->val.u16, d_ov++; |
|
111 break; |
|
112 case nsXPTType::T_U32 : |
|
113 if (gpr < 5) |
|
114 *((uint64_t*)d_gpr) = s->val.u32, d_gpr++, gpr++; |
|
115 else |
|
116 *((uint64_t*)d_ov ) = s->val.u32, d_ov++; |
|
117 break; |
|
118 case nsXPTType::T_U64 : |
|
119 if (gpr < 5) |
|
120 *((uint64_t*)d_gpr) = s->val.u64, d_gpr++, gpr++; |
|
121 else |
|
122 *((uint64_t*)d_ov ) = s->val.u64, d_ov++; |
|
123 break; |
|
124 case nsXPTType::T_FLOAT : |
|
125 if (fpr < 4) |
|
126 *((float*) d_fpr) = s->val.f, d_fpr++, fpr++; |
|
127 else |
|
128 *(((float*) d_ov )+1) = s->val.f, d_ov++; |
|
129 break; |
|
130 case nsXPTType::T_DOUBLE : |
|
131 if (fpr < 4) |
|
132 *((double*) d_fpr) = s->val.d, d_fpr++, fpr++; |
|
133 else |
|
134 *((double*) d_ov ) = s->val.d, d_ov++; |
|
135 break; |
|
136 case nsXPTType::T_BOOL : |
|
137 if (gpr < 5) |
|
138 *((uint64_t*)d_gpr) = s->val.b, d_gpr++, gpr++; |
|
139 else |
|
140 *((uint64_t*)d_ov ) = s->val.b, d_ov++; |
|
141 break; |
|
142 case nsXPTType::T_CHAR : |
|
143 if (gpr < 5) |
|
144 *((uint64_t*)d_gpr) = s->val.c, d_gpr++, gpr++; |
|
145 else |
|
146 *((uint64_t*)d_ov ) = s->val.c, d_ov++; |
|
147 break; |
|
148 case nsXPTType::T_WCHAR : |
|
149 if (gpr < 5) |
|
150 *((uint64_t*)d_gpr) = s->val.wc, d_gpr++, gpr++; |
|
151 else |
|
152 *((uint64_t*)d_ov ) = s->val.wc, d_ov++; |
|
153 break; |
|
154 default: |
|
155 // all the others are plain pointer types |
|
156 if (gpr < 5) |
|
157 *((void**) d_gpr) = s->val.p, d_gpr++, gpr++; |
|
158 else |
|
159 *((void**) d_ov ) = s->val.p, d_ov++; |
|
160 break; |
|
161 } |
|
162 } |
|
163 } |
|
164 |
|
165 typedef nsresult (*vtable_func)(nsISupports *, uint64_t, uint64_t, uint64_t, uint64_t, double, double, double, double); |
|
166 |
|
167 EXPORT_XPCOM_API(nsresult) |
|
168 NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, |
|
169 uint32_t paramCount, nsXPTCVariant* params) |
|
170 { |
|
171 vtable_func *vtable = *reinterpret_cast<vtable_func **>(that); |
|
172 vtable_func method = vtable[methodIndex]; |
|
173 uint64_t overflow = invoke_count_words (paramCount, params); |
|
174 uint64_t *stack_space = reinterpret_cast<uint64_t *>(__builtin_alloca((overflow + 8 /* 4 64-bits gpr + 4 64-bits fpr */) * 8)); |
|
175 uint64_t result; |
|
176 |
|
177 invoke_copy_to_stack(paramCount, params, stack_space, overflow); |
|
178 |
|
179 uint64_t *d_gpr = stack_space + overflow; |
|
180 double *d_fpr = reinterpret_cast<double *>(d_gpr + 4); |
|
181 |
|
182 return method(that, d_gpr[0], d_gpr[1], d_gpr[2], d_gpr[3], d_fpr[0], d_fpr[1], d_fpr[2], d_fpr[3]); |
|
183 } |
|
184 |