Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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/. */
7 // Platform specific code to invoke XPCOM methods on native objects
9 #include "xptcprivate.h"
11 // 6 integral parameters are passed in registers
12 const uint32_t GPR_COUNT = 6;
14 // 8 floating point parameters are passed in SSE registers
15 const uint32_t FPR_COUNT = 8;
17 // Remember that these 'words' are 64-bit long
18 static inline void
19 invoke_count_words(uint32_t paramCount, nsXPTCVariant * s,
20 uint32_t & nr_stack)
21 {
22 uint32_t nr_gpr;
23 uint32_t nr_fpr;
24 nr_gpr = 1; // skip one GP register for 'that'
25 nr_fpr = 0;
26 nr_stack = 0;
28 /* Compute number of eightbytes of class MEMORY. */
29 for (uint32_t i = 0; i < paramCount; i++, s++) {
30 if (!s->IsPtrData()
31 && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
32 if (nr_fpr < FPR_COUNT)
33 nr_fpr++;
34 else
35 nr_stack++;
36 }
37 else {
38 if (nr_gpr < GPR_COUNT)
39 nr_gpr++;
40 else
41 nr_stack++;
42 }
43 }
44 }
46 static void
47 invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
48 uint64_t * gpregs, double * fpregs)
49 {
50 uint32_t nr_gpr = 1; // skip one GP register for 'that'
51 uint32_t nr_fpr = 0;
52 uint64_t value;
54 for (uint32_t i = 0; i < paramCount; i++, s++) {
55 if (s->IsPtrData())
56 value = (uint64_t) s->ptr;
57 else {
58 switch (s->type) {
59 case nsXPTType::T_FLOAT: break;
60 case nsXPTType::T_DOUBLE: break;
61 case nsXPTType::T_I8: value = s->val.i8; break;
62 case nsXPTType::T_I16: value = s->val.i16; break;
63 case nsXPTType::T_I32: value = s->val.i32; break;
64 case nsXPTType::T_I64: value = s->val.i64; break;
65 case nsXPTType::T_U8: value = s->val.u8; break;
66 case nsXPTType::T_U16: value = s->val.u16; break;
67 case nsXPTType::T_U32: value = s->val.u32; break;
68 case nsXPTType::T_U64: value = s->val.u64; break;
69 case nsXPTType::T_BOOL: value = s->val.b; break;
70 case nsXPTType::T_CHAR: value = s->val.c; break;
71 case nsXPTType::T_WCHAR: value = s->val.wc; break;
72 default: value = (uint64_t) s->val.p; break;
73 }
74 }
76 if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
77 if (nr_fpr < FPR_COUNT)
78 fpregs[nr_fpr++] = s->val.d;
79 else {
80 *((double *)d) = s->val.d;
81 d++;
82 }
83 }
84 else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
85 if (nr_fpr < FPR_COUNT)
86 // The value in %xmm register is already prepared to
87 // be retrieved as a float. Therefore, we pass the
88 // value verbatim, as a double without conversion.
89 fpregs[nr_fpr++] = s->val.d;
90 else {
91 *((float *)d) = s->val.f;
92 d++;
93 }
94 }
95 else {
96 if (nr_gpr < GPR_COUNT)
97 gpregs[nr_gpr++] = value;
98 else
99 *d++ = value;
100 }
101 }
102 }
104 EXPORT_XPCOM_API(nsresult)
105 NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
106 uint32_t paramCount, nsXPTCVariant * params)
107 {
108 uint32_t nr_stack;
109 invoke_count_words(paramCount, params, nr_stack);
111 // Stack, if used, must be 16-bytes aligned
112 if (nr_stack)
113 nr_stack = (nr_stack + 1) & ~1;
115 // Load parameters to stack, if necessary
116 uint64_t *stack = (uint64_t *) __builtin_alloca(nr_stack * 8);
117 uint64_t gpregs[GPR_COUNT];
118 double fpregs[FPR_COUNT];
119 invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
121 // We used to have switches to make sure we would only load the registers
122 // that are needed for this call. That produced larger code that was
123 // not faster in practice. It also caused compiler warnings about the
124 // variables being used uninitialized.
125 // We now just load every every register. There could still be a warning
126 // from a memory analysis tools that we are loading uninitialized stack
127 // positions.
129 // FIXME: this function depends on the above __builtin_alloca placing
130 // the array in the correct spot for the ABI.
132 // Load FPR registers from fpregs[]
133 double d0, d1, d2, d3, d4, d5, d6, d7;
135 d7 = fpregs[7];
136 d6 = fpregs[6];
137 d5 = fpregs[5];
138 d4 = fpregs[4];
139 d3 = fpregs[3];
140 d2 = fpregs[2];
141 d1 = fpregs[1];
142 d0 = fpregs[0];
144 // Load GPR registers from gpregs[]
145 uint64_t a0, a1, a2, a3, a4, a5;
147 a5 = gpregs[5];
148 a4 = gpregs[4];
149 a3 = gpregs[3];
150 a2 = gpregs[2];
151 a1 = gpregs[1];
152 a0 = (uint64_t) that;
154 // Get pointer to method
155 uint64_t methodAddress = *((uint64_t *)that);
156 methodAddress += 8 * methodIndex;
157 methodAddress = *((uint64_t *)methodAddress);
159 typedef nsresult (*Method)(uint64_t, uint64_t, uint64_t, uint64_t,
160 uint64_t, uint64_t, double, double, double,
161 double, double, double, double, double);
162 nsresult result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5,
163 d0, d1, d2, d3, d4, d5,
164 d6, d7);
165 return result;
166 }