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_gpr, uint32_t & nr_fpr, uint32_t & nr_stack)
21 {
22 nr_gpr = 1; // skip one GP register for 'that'
23 nr_fpr = 0;
24 nr_stack = 0;
26 /* Compute number of eightbytes of class MEMORY. */
27 for (uint32_t i = 0; i < paramCount; i++, s++) {
28 if (!s->IsPtrData()
29 && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
30 if (nr_fpr < FPR_COUNT)
31 nr_fpr++;
32 else
33 nr_stack++;
34 }
35 else {
36 if (nr_gpr < GPR_COUNT)
37 nr_gpr++;
38 else
39 nr_stack++;
40 }
41 }
42 }
44 static void
45 invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
46 uint64_t * gpregs, double * fpregs)
47 {
48 uint32_t nr_gpr = 1; // skip one GP register for 'that'
49 uint32_t nr_fpr = 0;
50 uint64_t value;
52 for (uint32_t i = 0; i < paramCount; i++, s++) {
53 if (s->IsPtrData())
54 value = (uint64_t) s->ptr;
55 else {
56 switch (s->type) {
57 case nsXPTType::T_FLOAT: break;
58 case nsXPTType::T_DOUBLE: break;
59 case nsXPTType::T_I8: value = s->val.i8; break;
60 case nsXPTType::T_I16: value = s->val.i16; break;
61 case nsXPTType::T_I32: value = s->val.i32; break;
62 case nsXPTType::T_I64: value = s->val.i64; break;
63 case nsXPTType::T_U8: value = s->val.u8; break;
64 case nsXPTType::T_U16: value = s->val.u16; break;
65 case nsXPTType::T_U32: value = s->val.u32; break;
66 case nsXPTType::T_U64: value = s->val.u64; break;
67 case nsXPTType::T_BOOL: value = s->val.b; break;
68 case nsXPTType::T_CHAR: value = s->val.c; break;
69 case nsXPTType::T_WCHAR: value = s->val.wc; break;
70 default: value = (uint64_t) s->val.p; break;
71 }
72 }
74 if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
75 if (nr_fpr < FPR_COUNT)
76 fpregs[nr_fpr++] = s->val.d;
77 else {
78 *((double *)d) = s->val.d;
79 d++;
80 }
81 }
82 else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
83 if (nr_fpr < FPR_COUNT)
84 // The value in %xmm register is already prepared to
85 // be retrieved as a float. Therefore, we pass the
86 // value verbatim, as a double without conversion.
87 fpregs[nr_fpr++] = s->val.d;
88 else {
89 *((float *)d) = s->val.f;
90 d++;
91 }
92 }
93 else {
94 if (nr_gpr < GPR_COUNT)
95 gpregs[nr_gpr++] = value;
96 else
97 *d++ = value;
98 }
99 }
100 }
102 EXPORT_XPCOM_API(nsresult)
103 NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
104 uint32_t paramCount, nsXPTCVariant * params)
105 {
106 uint32_t nr_gpr, nr_fpr, nr_stack;
107 invoke_count_words(paramCount, params, nr_gpr, nr_fpr, nr_stack);
109 // Stack, if used, must be 16-bytes aligned
110 if (nr_stack)
111 nr_stack = (nr_stack + 1) & ~1;
113 // Load parameters to stack, if necessary
114 uint64_t *stack = (uint64_t *) __builtin_alloca(nr_stack * 8);
115 uint64_t gpregs[GPR_COUNT];
116 double fpregs[FPR_COUNT];
117 invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
119 // Load FPR registers from fpregs[]
120 register double d0 asm("xmm0");
121 register double d1 asm("xmm1");
122 register double d2 asm("xmm2");
123 register double d3 asm("xmm3");
124 register double d4 asm("xmm4");
125 register double d5 asm("xmm5");
126 register double d6 asm("xmm6");
127 register double d7 asm("xmm7");
129 switch (nr_fpr) {
130 #define ARG_FPR(N) \
131 case N+1: d##N = fpregs[N];
132 ARG_FPR(7);
133 ARG_FPR(6);
134 ARG_FPR(5);
135 ARG_FPR(4);
136 ARG_FPR(3);
137 ARG_FPR(2);
138 ARG_FPR(1);
139 ARG_FPR(0);
140 case 0:;
141 #undef ARG_FPR
142 }
144 // Load GPR registers from gpregs[]
145 register uint64_t a0 asm("rdi");
146 register uint64_t a1 asm("rsi");
147 register uint64_t a2 asm("rdx");
148 register uint64_t a3 asm("rcx");
149 register uint64_t a4 asm("r8");
150 register uint64_t a5 asm("r9");
152 switch (nr_gpr) {
153 #define ARG_GPR(N) \
154 case N+1: a##N = gpregs[N];
155 ARG_GPR(5);
156 ARG_GPR(4);
157 ARG_GPR(3);
158 ARG_GPR(2);
159 ARG_GPR(1);
160 case 1: a0 = (uint64_t) that;
161 case 0:;
162 #undef ARG_GPR
163 }
165 // Ensure that assignments to SSE registers won't be optimized away
166 asm("" ::
167 "x" (d0), "x" (d1), "x" (d2), "x" (d3),
168 "x" (d4), "x" (d5), "x" (d6), "x" (d7));
170 // Get pointer to method
171 uint64_t methodAddress = *((uint64_t *)that);
172 methodAddress += 8 * methodIndex;
173 methodAddress = *((uint64_t *)methodAddress);
175 typedef nsresult (*Method)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
176 nsresult result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5);
177 return result;
178 }