xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_unix.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

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.

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

mercurial