|
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 if (gpr < 5) gpr++; else overflow++; |
|
29 break; |
|
30 case nsXPTType::T_I64 : |
|
31 if (gpr < 4) gpr+=2; else gpr=5, overflow+=2; |
|
32 break; |
|
33 case nsXPTType::T_U8 : |
|
34 case nsXPTType::T_U16 : |
|
35 case nsXPTType::T_U32 : |
|
36 if (gpr < 5) gpr++; else overflow++; |
|
37 break; |
|
38 case nsXPTType::T_U64 : |
|
39 if (gpr < 4) gpr+=2; else gpr=5, overflow+=2; |
|
40 break; |
|
41 case nsXPTType::T_FLOAT : |
|
42 if (fpr < 2) fpr++; else overflow++; |
|
43 break; |
|
44 case nsXPTType::T_DOUBLE : |
|
45 if (fpr < 2) fpr++; else overflow+=2; |
|
46 break; |
|
47 case nsXPTType::T_BOOL : |
|
48 case nsXPTType::T_CHAR : |
|
49 case nsXPTType::T_WCHAR : |
|
50 if (gpr < 5) gpr++; else overflow++; |
|
51 break; |
|
52 default: |
|
53 // all the others are plain pointer types |
|
54 if (gpr < 5) gpr++; else overflow++; |
|
55 break; |
|
56 } |
|
57 } |
|
58 /* Round up number of overflow words to ensure stack |
|
59 stays aligned to 8 bytes. */ |
|
60 return (overflow + 1) & ~1; |
|
61 } |
|
62 |
|
63 static void |
|
64 invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d_ov, uint32_t overflow) |
|
65 { |
|
66 uint32_t *d_gpr = d_ov + overflow; |
|
67 uint64_t *d_fpr = (uint64_t *)(d_gpr + 4); |
|
68 uint32_t gpr = 1 /*this*/, fpr = 0; |
|
69 |
|
70 for(uint32_t i = 0; i < paramCount; i++, s++) |
|
71 { |
|
72 if(s->IsPtrData()) |
|
73 { |
|
74 if (gpr < 5) |
|
75 *((void**)d_gpr) = s->ptr, d_gpr++, gpr++; |
|
76 else |
|
77 *((void**)d_ov ) = s->ptr, d_ov++; |
|
78 continue; |
|
79 } |
|
80 switch(s->type) |
|
81 { |
|
82 case nsXPTType::T_I8 : |
|
83 if (gpr < 5) |
|
84 *((int32_t*) d_gpr) = s->val.i8, d_gpr++, gpr++; |
|
85 else |
|
86 *((int32_t*) d_ov ) = s->val.i8, d_ov++; |
|
87 break; |
|
88 case nsXPTType::T_I16 : |
|
89 if (gpr < 5) |
|
90 *((int32_t*) d_gpr) = s->val.i16, d_gpr++, gpr++; |
|
91 else |
|
92 *((int32_t*) d_ov ) = s->val.i16, d_ov++; |
|
93 break; |
|
94 case nsXPTType::T_I32 : |
|
95 if (gpr < 5) |
|
96 *((int32_t*) d_gpr) = s->val.i32, d_gpr++, gpr++; |
|
97 else |
|
98 *((int32_t*) d_ov ) = s->val.i32, d_ov++; |
|
99 break; |
|
100 case nsXPTType::T_I64 : |
|
101 if (gpr < 4) |
|
102 *((int64_t*) d_gpr) = s->val.i64, d_gpr+=2, gpr+=2; |
|
103 else |
|
104 *((int64_t*) d_ov ) = s->val.i64, d_ov+=2, gpr=5; |
|
105 break; |
|
106 case nsXPTType::T_U8 : |
|
107 if (gpr < 5) |
|
108 *((uint32_t*) d_gpr) = s->val.u8, d_gpr++, gpr++; |
|
109 else |
|
110 *((uint32_t*) d_ov ) = s->val.u8, d_ov++; |
|
111 break; |
|
112 case nsXPTType::T_U16 : |
|
113 if (gpr < 5) |
|
114 *((uint32_t*)d_gpr) = s->val.u16, d_gpr++, gpr++; |
|
115 else |
|
116 *((uint32_t*)d_ov ) = s->val.u16, d_ov++; |
|
117 break; |
|
118 case nsXPTType::T_U32 : |
|
119 if (gpr < 5) |
|
120 *((uint32_t*)d_gpr) = s->val.u32, d_gpr++, gpr++; |
|
121 else |
|
122 *((uint32_t*)d_ov ) = s->val.u32, d_ov++; |
|
123 break; |
|
124 case nsXPTType::T_U64 : |
|
125 if (gpr < 4) |
|
126 *((uint64_t*)d_gpr) = s->val.u64, d_gpr+=2, gpr+=2; |
|
127 else |
|
128 *((uint64_t*)d_ov ) = s->val.u64, d_ov+=2, gpr=5; |
|
129 break; |
|
130 case nsXPTType::T_FLOAT : |
|
131 if (fpr < 2) |
|
132 *((float*) d_fpr) = s->val.f, d_fpr++, fpr++; |
|
133 else |
|
134 *((float*) d_ov ) = s->val.f, d_ov++; |
|
135 break; |
|
136 case nsXPTType::T_DOUBLE : |
|
137 if (fpr < 2) |
|
138 *((double*) d_fpr) = s->val.d, d_fpr++, fpr++; |
|
139 else |
|
140 *((double*) d_ov ) = s->val.d, d_ov+=2; |
|
141 break; |
|
142 case nsXPTType::T_BOOL : |
|
143 if (gpr < 5) |
|
144 *((uint32_t*)d_gpr) = s->val.b, d_gpr++, gpr++; |
|
145 else |
|
146 *((uint32_t*)d_ov ) = s->val.b, d_ov++; |
|
147 break; |
|
148 case nsXPTType::T_CHAR : |
|
149 if (gpr < 5) |
|
150 *((uint32_t*)d_gpr) = s->val.c, d_gpr++, gpr++; |
|
151 else |
|
152 *((uint32_t*)d_ov ) = s->val.c, d_ov++; |
|
153 break; |
|
154 case nsXPTType::T_WCHAR : |
|
155 if (gpr < 5) |
|
156 *((uint32_t*)d_gpr) = s->val.wc, d_gpr++, gpr++; |
|
157 else |
|
158 *((uint32_t*)d_ov ) = s->val.wc, d_ov++; |
|
159 break; |
|
160 default: |
|
161 // all the others are plain pointer types |
|
162 if (gpr < 5) |
|
163 *((void**) d_gpr) = s->val.p, d_gpr++, gpr++; |
|
164 else |
|
165 *((void**) d_ov ) = s->val.p, d_ov++; |
|
166 break; |
|
167 } |
|
168 } |
|
169 } |
|
170 |
|
171 typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t, uint32_t, double, double); |
|
172 |
|
173 EXPORT_XPCOM_API(nsresult) |
|
174 NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, |
|
175 uint32_t paramCount, nsXPTCVariant* params) |
|
176 { |
|
177 vtable_func *vtable = *reinterpret_cast<vtable_func **>(that); |
|
178 vtable_func method = vtable[methodIndex]; |
|
179 uint32_t overflow = invoke_count_words (paramCount, params); |
|
180 uint32_t *stack_space = reinterpret_cast<uint32_t *>(__builtin_alloca((overflow + 8 /* 4 32-bits gpr + 2 64-bits fpr */) * 4)); |
|
181 |
|
182 invoke_copy_to_stack(paramCount, params, stack_space, overflow); |
|
183 |
|
184 uint32_t *d_gpr = stack_space + overflow; |
|
185 double *d_fpr = reinterpret_cast<double *>(d_gpr + 4); |
|
186 |
|
187 return method(that, d_gpr[0], d_gpr[1], d_gpr[2], d_gpr[3], d_fpr[0], d_fpr[1]); |
|
188 } |
|
189 |