1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 /* Implement shared vtbl methods. */
7 
8 #include "xptcprivate.h"
9 
10 /*
11  * This is for AArch64 ABI
12  *
13  * When we're called, the "gp" registers are stored in gprData and
14  * the "fp" registers are stored in fprData. Each array has 8 regs
15  * but first reg in gprData is a placeholder for 'self'.
16  */
17 extern "C" nsresult
PrepareAndDispatch(nsXPTCStubBase * self,uint32_t methodIndex,uint64_t * args,uint64_t * gprData,double * fprData)18 PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args,
19                    uint64_t *gprData, double *fprData)
20 {
21 #define PARAM_BUFFER_COUNT        16
22 #define PARAM_GPR_COUNT            8
23 #define PARAM_FPR_COUNT            8
24 
25     nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
26     nsXPTCMiniVariant* dispatchParams = NULL;
27     const nsXPTMethodInfo* info;
28 
29     NS_ASSERTION(self,"no self");
30 
31     self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
32     NS_ASSERTION(info,"no method info");
33 
34     uint32_t paramCount = info->GetParamCount();
35 
36     // setup variant array pointer
37     if (paramCount > PARAM_BUFFER_COUNT) {
38         dispatchParams = new nsXPTCMiniVariant[paramCount];
39     } else {
40         dispatchParams = paramBuffer;
41     }
42     NS_ASSERTION(dispatchParams,"no place for params");
43 
44     const uint8_t indexOfJSContext = info->IndexOfJSContext();
45 
46     uint64_t* ap = args;
47     uint32_t next_gpr = 1; // skip first arg which is 'self'
48     uint32_t next_fpr = 0;
49     for (uint32_t i = 0; i < paramCount; i++) {
50         const nsXPTParamInfo& param = info->GetParam(i);
51         const nsXPTType& type = param.GetType();
52         nsXPTCMiniVariant* dp = &dispatchParams[i];
53 
54         if (i == indexOfJSContext) {
55             if (next_gpr < PARAM_GPR_COUNT)
56                 next_gpr++;
57             else
58                 ap++;
59         }
60 
61         if (param.IsOut() || !type.IsArithmetic()) {
62             if (next_gpr < PARAM_GPR_COUNT) {
63                 dp->val.p = (void*)gprData[next_gpr++];
64             } else {
65                 dp->val.p = (void*)*ap++;
66             }
67             continue;
68         }
69 
70         switch (type) {
71             case nsXPTType::T_I8:
72                 if (next_gpr < PARAM_GPR_COUNT) {
73                     dp->val.i8  = (int8_t)gprData[next_gpr++];
74                 } else {
75                     dp->val.i8  = (int8_t)*ap++;
76                 }
77                 break;
78 
79             case nsXPTType::T_I16:
80                 if (next_gpr < PARAM_GPR_COUNT) {
81                     dp->val.i16  = (int16_t)gprData[next_gpr++];
82                 } else {
83                     dp->val.i16  = (int16_t)*ap++;
84                 }
85                 break;
86 
87             case nsXPTType::T_I32:
88                 if (next_gpr < PARAM_GPR_COUNT) {
89                     dp->val.i32  = (int32_t)gprData[next_gpr++];
90                 } else {
91                     dp->val.i32  = (int32_t)*ap++;
92                 }
93                 break;
94 
95             case nsXPTType::T_I64:
96                 if (next_gpr < PARAM_GPR_COUNT) {
97                     dp->val.i64  = (int64_t)gprData[next_gpr++];
98                 } else {
99                     dp->val.i64  = (int64_t)*ap++;
100                 }
101                 break;
102 
103             case nsXPTType::T_U8:
104                 if (next_gpr < PARAM_GPR_COUNT) {
105                     dp->val.u8  = (uint8_t)gprData[next_gpr++];
106                 } else {
107                     dp->val.u8  = (uint8_t)*ap++;
108                 }
109                 break;
110 
111             case nsXPTType::T_U16:
112                 if (next_gpr < PARAM_GPR_COUNT) {
113                     dp->val.u16  = (uint16_t)gprData[next_gpr++];
114                 } else {
115                     dp->val.u16  = (uint16_t)*ap++;
116                 }
117                 break;
118 
119             case nsXPTType::T_U32:
120                 if (next_gpr < PARAM_GPR_COUNT) {
121                     dp->val.u32  = (uint32_t)gprData[next_gpr++];
122                 } else {
123                     dp->val.u32  = (uint32_t)*ap++;
124                 }
125                 break;
126 
127             case nsXPTType::T_U64:
128                 if (next_gpr < PARAM_GPR_COUNT) {
129                     dp->val.u64  = (uint64_t)gprData[next_gpr++];
130                 } else {
131                     dp->val.u64  = (uint64_t)*ap++;
132                 }
133                 break;
134 
135             case nsXPTType::T_FLOAT:
136                 if (next_fpr < PARAM_FPR_COUNT) {
137                     memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f));
138                 } else {
139                     memcpy(&dp->val.f, ap++, sizeof(dp->val.f));
140                 }
141                 break;
142 
143             case nsXPTType::T_DOUBLE:
144                 if (next_fpr < PARAM_FPR_COUNT) {
145                     memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d));
146                 } else {
147                     memcpy(&dp->val.d, ap++, sizeof(dp->val.d));
148                 }
149                 break;
150 
151             case nsXPTType::T_BOOL:
152                 if (next_gpr < PARAM_GPR_COUNT) {
153                     dp->val.b  = (bool)(uint8_t)gprData[next_gpr++];
154                 } else {
155                     dp->val.b  = (bool)(uint8_t)*ap++;
156                 }
157                 break;
158 
159             case nsXPTType::T_CHAR:
160                 if (next_gpr < PARAM_GPR_COUNT) {
161                     dp->val.c  = (char)gprData[next_gpr++];
162                 } else {
163                     dp->val.c  = (char)*ap++;
164                 }
165                 break;
166 
167             case nsXPTType::T_WCHAR:
168                 if (next_gpr < PARAM_GPR_COUNT) {
169                     dp->val.wc  = (wchar_t)gprData[next_gpr++];
170                 } else {
171                     dp->val.wc  = (wchar_t)*ap++;
172                 }
173                 break;
174 
175             default:
176                 NS_ASSERTION(0, "bad type");
177                 break;
178         }
179     }
180 
181     nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
182                                                dispatchParams);
183 
184     if (dispatchParams != paramBuffer) {
185         delete [] dispatchParams;
186     }
187 
188     return result;
189 }
190 
191 #define STUB_ENTRY(n)  /* defined in the assembly file */
192 
193 #define SENTINEL_ENTRY(n) \
194 nsresult nsXPTCStubBase::Sentinel##n() \
195 { \
196     NS_ERROR("nsXPTCStubBase::Sentinel called"); \
197     return NS_ERROR_NOT_IMPLEMENTED; \
198 }
199 
200 #include "xptcstubsdef.inc"
201